Skip to content

Commit 83ba830

Browse files
committed
feat(mcp): human-written table/column descriptions for the schema catalog (#1212)
Synced from sferarc/pgbeam@8dee15f
1 parent 3f17914 commit 83ba830

8 files changed

Lines changed: 683 additions & 1 deletion

openapi.json

Lines changed: 272 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,11 @@
6363
"description": "Decoy (canary) relations that trip on agent access",
6464
"x-icon": "Fingerprint"
6565
},
66+
{
67+
"name": "SchemaAnnotations",
68+
"description": "Human-written table and column descriptions for the schema catalog",
69+
"x-icon": "BookText"
70+
},
6671
{
6772
"name": "Anomalies",
6873
"description": "Anomalous-behavior alerts surfaced by the gateway",
@@ -3301,6 +3306,159 @@
33013306
}
33023307
}
33033308
},
3309+
"/v1/projects/{project_id}/schema-annotations": {
3310+
"parameters": [
3311+
{
3312+
"$ref": "#/components/parameters/ProjectId"
3313+
}
3314+
],
3315+
"get": {
3316+
"operationId": "listSchemaAnnotations",
3317+
"summary": "List schema annotations",
3318+
"description": "Lists the project's human-written table and column descriptions. These are surfaced to connected agents through the MCP schema catalog.\n",
3319+
"tags": [
3320+
"SchemaAnnotations"
3321+
],
3322+
"parameters": [
3323+
{
3324+
"$ref": "#/components/parameters/PageSize"
3325+
},
3326+
{
3327+
"$ref": "#/components/parameters/PageToken"
3328+
}
3329+
],
3330+
"responses": {
3331+
"200": {
3332+
"description": "List of schema annotations.",
3333+
"content": {
3334+
"application/json": {
3335+
"schema": {
3336+
"$ref": "#/components/schemas/ListSchemaAnnotationsResponse"
3337+
}
3338+
}
3339+
}
3340+
},
3341+
"400": {
3342+
"$ref": "#/components/responses/BadRequest"
3343+
},
3344+
"401": {
3345+
"$ref": "#/components/responses/Unauthorized"
3346+
},
3347+
"403": {
3348+
"$ref": "#/components/responses/Forbidden"
3349+
},
3350+
"404": {
3351+
"$ref": "#/components/responses/NotFound"
3352+
},
3353+
"429": {
3354+
"$ref": "#/components/responses/TooManyRequests"
3355+
}
3356+
}
3357+
},
3358+
"put": {
3359+
"operationId": "putSchemaAnnotation",
3360+
"summary": "Create or replace a schema annotation",
3361+
"description": "Attaches an operator-written description to a table (omit column_name) or a column. Keyed by (schema_name, table_name, column_name); an existing annotation with the same key is replaced.\n",
3362+
"tags": [
3363+
"SchemaAnnotations"
3364+
],
3365+
"requestBody": {
3366+
"required": true,
3367+
"content": {
3368+
"application/json": {
3369+
"schema": {
3370+
"$ref": "#/components/schemas/SchemaAnnotationInput"
3371+
}
3372+
}
3373+
}
3374+
},
3375+
"responses": {
3376+
"200": {
3377+
"description": "The created or updated annotation.",
3378+
"content": {
3379+
"application/json": {
3380+
"schema": {
3381+
"$ref": "#/components/schemas/SchemaAnnotation"
3382+
}
3383+
}
3384+
}
3385+
},
3386+
"400": {
3387+
"$ref": "#/components/responses/BadRequest"
3388+
},
3389+
"401": {
3390+
"$ref": "#/components/responses/Unauthorized"
3391+
},
3392+
"403": {
3393+
"$ref": "#/components/responses/Forbidden"
3394+
},
3395+
"404": {
3396+
"$ref": "#/components/responses/NotFound"
3397+
},
3398+
"429": {
3399+
"$ref": "#/components/responses/TooManyRequests"
3400+
}
3401+
}
3402+
},
3403+
"delete": {
3404+
"operationId": "deleteSchemaAnnotation",
3405+
"summary": "Delete a schema annotation",
3406+
"description": "Removes a single annotation identified by its natural key. Omit column_name to delete a table-level annotation, and omit schema_name to match the unqualified form.\n",
3407+
"tags": [
3408+
"SchemaAnnotations"
3409+
],
3410+
"parameters": [
3411+
{
3412+
"name": "table_name",
3413+
"in": "query",
3414+
"required": true,
3415+
"description": "Relation (table or view) the annotation describes.",
3416+
"schema": {
3417+
"type": "string",
3418+
"minLength": 1,
3419+
"maxLength": 255
3420+
}
3421+
},
3422+
{
3423+
"name": "schema_name",
3424+
"in": "query",
3425+
"required": false,
3426+
"description": "Optional schema. Omit to match the unqualified form.",
3427+
"schema": {
3428+
"type": "string",
3429+
"maxLength": 255
3430+
}
3431+
},
3432+
{
3433+
"name": "column_name",
3434+
"in": "query",
3435+
"required": false,
3436+
"description": "Optional column. Omit to delete a table-level annotation.",
3437+
"schema": {
3438+
"type": "string",
3439+
"maxLength": 255
3440+
}
3441+
}
3442+
],
3443+
"responses": {
3444+
"204": {
3445+
"description": "Annotation deleted."
3446+
},
3447+
"400": {
3448+
"$ref": "#/components/responses/BadRequest"
3449+
},
3450+
"401": {
3451+
"$ref": "#/components/responses/Unauthorized"
3452+
},
3453+
"403": {
3454+
"$ref": "#/components/responses/Forbidden"
3455+
},
3456+
"404": {
3457+
"$ref": "#/components/responses/NotFound"
3458+
}
3459+
}
3460+
}
3461+
},
33043462
"/v1/organizations/{org_id}/self-host-enrollments": {
33053463
"parameters": [
33063464
{
@@ -8601,6 +8759,120 @@
86018759
}
86028760
}
86038761
},
8762+
"SchemaAnnotation": {
8763+
"type": "object",
8764+
"description": "A human-written description for a table or column, attached by a project operator and surfaced through the agent-facing MCP catalog. When present it takes precedence over the DB-native comment for the same relation or column.\n",
8765+
"required": [
8766+
"id",
8767+
"project_id",
8768+
"table_name",
8769+
"description",
8770+
"created_at",
8771+
"updated_at"
8772+
],
8773+
"properties": {
8774+
"id": {
8775+
"type": "string",
8776+
"description": "Unique annotation identifier.",
8777+
"example": "sca_01j9x8y7z6w5v4u3t2s1r0q9p8"
8778+
},
8779+
"project_id": {
8780+
"type": "string",
8781+
"description": "Project the annotation belongs to.",
8782+
"example": "prj_01j9x8y7z6w5v4u3t2s1r0q9p8"
8783+
},
8784+
"schema_name": {
8785+
"type": "string",
8786+
"nullable": true,
8787+
"description": "Optional schema. Null matches the unqualified form, mirroring the relation allowlist normalization.\n",
8788+
"example": "public"
8789+
},
8790+
"table_name": {
8791+
"type": "string",
8792+
"description": "Relation (table or view) the annotation describes.",
8793+
"example": "users"
8794+
},
8795+
"column_name": {
8796+
"type": "string",
8797+
"nullable": true,
8798+
"description": "Optional column. Null means the annotation describes the table itself.\n",
8799+
"example": "email"
8800+
},
8801+
"description": {
8802+
"type": "string",
8803+
"description": "The operator-written description text.",
8804+
"example": "Primary customer account. One row per signed-up user."
8805+
},
8806+
"created_at": {
8807+
"type": "string",
8808+
"format": "date-time",
8809+
"description": "When the annotation was created."
8810+
},
8811+
"updated_at": {
8812+
"type": "string",
8813+
"format": "date-time",
8814+
"description": "When the annotation was last updated."
8815+
}
8816+
}
8817+
},
8818+
"SchemaAnnotationInput": {
8819+
"type": "object",
8820+
"description": "Request body for creating or replacing a schema annotation. Keyed by (schema_name, table_name, column_name); an existing annotation with the same key is replaced.\n",
8821+
"required": [
8822+
"table_name",
8823+
"description"
8824+
],
8825+
"properties": {
8826+
"schema_name": {
8827+
"type": "string",
8828+
"nullable": true,
8829+
"maxLength": 255,
8830+
"description": "Optional schema. Null or empty matches the unqualified form.",
8831+
"example": "public"
8832+
},
8833+
"table_name": {
8834+
"type": "string",
8835+
"minLength": 1,
8836+
"maxLength": 255,
8837+
"description": "Relation (table or view) the annotation describes.",
8838+
"example": "users"
8839+
},
8840+
"column_name": {
8841+
"type": "string",
8842+
"nullable": true,
8843+
"maxLength": 255,
8844+
"description": "Optional column. Null describes the table itself.",
8845+
"example": "email"
8846+
},
8847+
"description": {
8848+
"type": "string",
8849+
"minLength": 1,
8850+
"maxLength": 4096,
8851+
"description": "The operator-written description text.",
8852+
"example": "Primary customer account. One row per signed-up user."
8853+
}
8854+
}
8855+
},
8856+
"ListSchemaAnnotationsResponse": {
8857+
"type": "object",
8858+
"description": "Cursor-paginated schema annotations for a project.",
8859+
"required": [
8860+
"annotations"
8861+
],
8862+
"properties": {
8863+
"annotations": {
8864+
"type": "array",
8865+
"description": "Annotations returned for the current page.",
8866+
"items": {
8867+
"$ref": "#/components/schemas/SchemaAnnotation"
8868+
}
8869+
},
8870+
"next_page_token": {
8871+
"type": "string",
8872+
"description": "Opaque token for cursor-based pagination."
8873+
}
8874+
}
8875+
},
86048876
"SchemaCatalogColumn": {
86058877
"type": "object",
86068878
"description": "One column of a relation in the schema catalog.",

0 commit comments

Comments
 (0)