5.12-b Write tools, non-destructive (phase 2)
- Dominant language
- JavaScript
- Stars
- 400
- Forks
- 89
- Avg merge
- 1d 21h
- Merged PRs (30d)
- 146
Description
**Parent:** #7681 (5.12 Team data and packages)
**Tool file:** new `forge/ee/lib/mcp/tools/teamData.js`
`readOnlyHint: false`, `destructiveHint: false`. One tool per endpoint; these siblings do not share a single action concept, so they are not consolidated.
| Tool | Endpoint | Scope | Annotation |
|---|---|---|---|
| `platform_create_database_table` | `POST /teams/:teamId/databases/:databaseId/tables` | `team:database:create` | write |
| `platform_create_library_entry` | `POST /storage/library/:libraryId/*` | `library:entry:create` | write |
| `platform_update_git_token` | `PUT /teams/:teamId/git/tokens/:tokenId` | `team:git:tokens:edit` | write |
**Design notes:**
- Plan-gated (enabled per team type/plan, not per user role): `tables`, `npm`, `gitIntegration`, `shared-library`. If the team's plan does not include the feature the route returns a 404 (`Not Found - not available on team`), independent of the PAT's permissions. The tool should surface this as a clear "feature not enabled for this team" message rather than passing through a bare "not found", which an agent would misread as a missing resource.
- `update_git_token` edits an existing token record; it does not mint or return a new credential (the minting POST is excluded, see 5.12-d).
**Tool definitions (description + zod inputSchema):**
```js
platform_create_database_table: {
description: 'Creates a new table in a database. Both name and columns are required to create the table.',
inputSchema: z.object({
teamId: z.string().describe('team hashid'),
databaseId: z.string().describe('database hashid'),
name: z.string().describe('name for the new table'),
columns: z.array(z.object({
name: z.string().describe('column name'),
type: z.string().describe('column data type (free-form string; the API declares no enum)'),
nullable: z.boolean().optional().describe('whether the column allows NULL'),
default: z.string().nullable().optional().describe('default value, or null for none'),
generated: z.boolean().optional().describe('whether the column value is generated'),
maxLength: z.number().nullable().optional().describe('maximum length, or null for unbounded')
})).describe('column definitions for the new table')
})
},
platform_create_library_entry: {
description: 'Creates an entry in the team shared library. type is required and a missing type is rejected with a 400 error. When body is an object it is JSON-stringified before storage.',
inputSchema: z.object({
libraryId: z.string().describe('shared-library hashid (the team hashid)'),
path: z.string().describe('Library entry path'),
type: z.string().describe('entry type (e.g. flows, functions)'),
body: z.any().describe('entry contents'),
meta: z.record(z.any()).optional().describe('arbitrary metadata stored with the entry')
})
},
platform_update_git_token: {
description: 'Updates an existing git token. name is the only editable field: the update only changes the token name and never mints or returns a credential.',
inputSchema: z.object({
teamId: z.string().describe('team hashid'),
tokenId: z.string().describe('git token hashid'),
name: z.string().describe('new name for the git token')
})
}
```
**Tests:**
- Read-only PAT rejected for every tool here.
- Feature-disabled team returns the descriptive gate error.
---
Contributor guide
Research direction
Start with the new forge/ee/lib/mcp/tools/teamData.js entry point and inspect sibling MCP tools for endpoint registration, Zod schemas, and error handling. Add the three specified tools and tests for read-only PAT rejection and the descriptive feature-disabled team error. Done means all listed inputs and annotations are represented, including the update_git_token restriction, and the tests pass.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript
- Domain
- api, backend, devtools
- Issue type
- Feature
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 72/100