@ebitex/content-mcp 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/README.md +102 -0
  2. package/dist/client.d.ts +34 -0
  3. package/dist/client.d.ts.map +1 -0
  4. package/dist/client.js +63 -0
  5. package/dist/client.js.map +1 -0
  6. package/dist/config.d.ts +42 -0
  7. package/dist/config.d.ts.map +1 -0
  8. package/dist/config.js +62 -0
  9. package/dist/config.js.map +1 -0
  10. package/dist/errors.d.ts +43 -0
  11. package/dist/errors.d.ts.map +1 -0
  12. package/dist/errors.js +82 -0
  13. package/dist/errors.js.map +1 -0
  14. package/dist/index.d.ts +14 -0
  15. package/dist/index.d.ts.map +1 -0
  16. package/dist/index.js +14 -0
  17. package/dist/index.js.map +1 -0
  18. package/dist/main.d.ts +3 -0
  19. package/dist/main.d.ts.map +1 -0
  20. package/dist/main.js +35 -0
  21. package/dist/main.js.map +1 -0
  22. package/dist/resources/helpCorpus.generated.d.ts +7 -0
  23. package/dist/resources/helpCorpus.generated.d.ts.map +1 -0
  24. package/dist/resources/helpCorpus.generated.js +112 -0
  25. package/dist/resources/helpCorpus.generated.js.map +1 -0
  26. package/dist/resources/register.d.ts +8 -0
  27. package/dist/resources/register.d.ts.map +1 -0
  28. package/dist/resources/register.js +73 -0
  29. package/dist/resources/register.js.map +1 -0
  30. package/dist/routes.d.ts +68 -0
  31. package/dist/routes.d.ts.map +1 -0
  32. package/dist/routes.js +173 -0
  33. package/dist/routes.js.map +1 -0
  34. package/dist/server.d.ts +32 -0
  35. package/dist/server.d.ts.map +1 -0
  36. package/dist/server.js +65 -0
  37. package/dist/server.js.map +1 -0
  38. package/dist/session.d.ts +45 -0
  39. package/dist/session.d.ts.map +1 -0
  40. package/dist/session.js +71 -0
  41. package/dist/session.js.map +1 -0
  42. package/dist/tools/register.d.ts +26 -0
  43. package/dist/tools/register.d.ts.map +1 -0
  44. package/dist/tools/register.js +212 -0
  45. package/dist/tools/register.js.map +1 -0
  46. package/dist/tools/result.d.ts +28 -0
  47. package/dist/tools/result.d.ts.map +1 -0
  48. package/dist/tools/result.js +26 -0
  49. package/dist/tools/result.js.map +1 -0
  50. package/package.json +39 -0
@@ -0,0 +1,68 @@
1
+ /**
2
+ * The `kind`-to-route table — SPEC.md's Business Logic §9.
3
+ *
4
+ * **This is the only content-model knowledge this server holds, and it is not much: which URL a
5
+ * kind lives at.** It knows nothing about what a Contract may contain, what field types exist, or
6
+ * what makes a document valid. Those are answered at runtime by the API (`content_describe` for the
7
+ * first two, the write's own response for the third), which is what makes this server unable to
8
+ * drift from the product — there is no second copy of the model here to fall out of step.
9
+ *
10
+ * The table is worth reading carefully, because a reader who assumed a uniform `POST /{kind}` /
11
+ * `PUT /{kind}/{id}` shape would get four things wrong, all found by checking the routes as mapped
12
+ * rather than by reading endpoint file names:
13
+ *
14
+ * - **An Adapter updates with `PATCH`.** Every other family takes `PUT`. `PUT /adapters/{id}` does
15
+ * not exist, so assuming uniformity builds clean and answers `405` at run time — on the one
16
+ * family whose mapping canvas is the hardest thing an agent will try to author.
17
+ * - **A node's payload is its own route**, so it is its own kind. `PUT /experience/nodes/{id}`
18
+ * carries identity and location and *not* the payload; folding them together would put a silent
19
+ * no-op behind a successful write, which is worse than a refusal.
20
+ * - **A site is not a node.** `POST /experience/sites` creates a root; a page under it is a
21
+ * separate call to `/experience/nodes`.
22
+ * - **The surface is not uniformly CRUD.** Folders, audiences, sites and both taxonomy kinds have
23
+ * no single-entity `GET` at all — they are read by listing. `readOne: null` records that rather
24
+ * than inventing a route that would 404.
25
+ *
26
+ * Anything not in this table is not reachable by this server, and that is the same default-closed
27
+ * posture the server's own allow-list takes (`ContentManagementRouteScopes.RequiredScope` returns
28
+ * null for an unknown segment, which the filter treats as a refusal). Workflow, providers,
29
+ * environments, promotion and credential minting have no row because spec #641 admits none of them.
30
+ */
31
+ export declare const WRITABLE_KINDS: readonly ["contract", "template", "component", "folder", "site", "node", "nodePayload", "adapter", "stream", "audience", "categoryGroup", "category"];
32
+ export type EntityKind = (typeof WRITABLE_KINDS)[number];
33
+ export type KindRoutes = {
34
+ /** What this kind is called in prose, for messages an agent reads. */
35
+ label: string;
36
+ /** `POST` target, or null where the kind cannot be created on its own (a node's payload). */
37
+ create: string | null;
38
+ /** Path template for update/delete/read, `{id}` substituted. Null where the verb does not exist. */
39
+ update: {
40
+ method: 'PUT' | 'PATCH';
41
+ path: string;
42
+ } | null;
43
+ remove: string | null;
44
+ /** Single-entity `GET`, or null for a family that is only listable. */
45
+ readOne: string | null;
46
+ /** Listing route, which is also how a `readOne: null` kind is read. */
47
+ list: string | null;
48
+ };
49
+ export declare function isEntityKind(value: string): value is EntityKind;
50
+ export declare function routesFor(kind: EntityKind): KindRoutes;
51
+ /**
52
+ * Substitutes `{id}` in a path template.
53
+ *
54
+ * Encoded, because every id here is a Guid today and will not always be — a stream is addressable by
55
+ * external id on the delivery side already, and an id that ever carries a slash would otherwise
56
+ * silently change which route was matched.
57
+ */
58
+ export declare function withId(template: string, id: string): string;
59
+ /**
60
+ * The message a kind this server cannot reach gets.
61
+ *
62
+ * It answers locally rather than sending the request to earn a `404`, because the `404` says only
63
+ * "no such route" — it does not say which kinds *are* writable, which is the one thing that gets the
64
+ * agent to its next call. This is the same instinct as §3's verbatim relay pointed the other way:
65
+ * be transparent about what the server knows, and say nothing it does not.
66
+ */
67
+ export declare function unknownKindMessage(kind: string): string;
68
+ //# sourceMappingURL=routes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../src/routes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,eAAO,MAAM,cAAc,uJAajB,CAAA;AAEV,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,CAAC,CAAA;AAExD,MAAM,MAAM,UAAU,GAAG;IACvB,sEAAsE;IACtE,KAAK,EAAE,MAAM,CAAA;IACb,6FAA6F;IAC7F,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,oGAAoG;IACpG,MAAM,EAAE;QAAE,MAAM,EAAE,KAAK,GAAG,OAAO,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAA;IACxD,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,uEAAuE;IACvE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,uEAAuE;IACvE,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;CACpB,CAAA;AAsGD,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,UAAU,CAE/D;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,UAAU,GAAG,UAAU,CAEtD;AAED;;;;;;GAMG;AACH,wBAAgB,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,CAE3D;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAMvD"}
package/dist/routes.js ADDED
@@ -0,0 +1,173 @@
1
+ /**
2
+ * The `kind`-to-route table — SPEC.md's Business Logic §9.
3
+ *
4
+ * **This is the only content-model knowledge this server holds, and it is not much: which URL a
5
+ * kind lives at.** It knows nothing about what a Contract may contain, what field types exist, or
6
+ * what makes a document valid. Those are answered at runtime by the API (`content_describe` for the
7
+ * first two, the write's own response for the third), which is what makes this server unable to
8
+ * drift from the product — there is no second copy of the model here to fall out of step.
9
+ *
10
+ * The table is worth reading carefully, because a reader who assumed a uniform `POST /{kind}` /
11
+ * `PUT /{kind}/{id}` shape would get four things wrong, all found by checking the routes as mapped
12
+ * rather than by reading endpoint file names:
13
+ *
14
+ * - **An Adapter updates with `PATCH`.** Every other family takes `PUT`. `PUT /adapters/{id}` does
15
+ * not exist, so assuming uniformity builds clean and answers `405` at run time — on the one
16
+ * family whose mapping canvas is the hardest thing an agent will try to author.
17
+ * - **A node's payload is its own route**, so it is its own kind. `PUT /experience/nodes/{id}`
18
+ * carries identity and location and *not* the payload; folding them together would put a silent
19
+ * no-op behind a successful write, which is worse than a refusal.
20
+ * - **A site is not a node.** `POST /experience/sites` creates a root; a page under it is a
21
+ * separate call to `/experience/nodes`.
22
+ * - **The surface is not uniformly CRUD.** Folders, audiences, sites and both taxonomy kinds have
23
+ * no single-entity `GET` at all — they are read by listing. `readOne: null` records that rather
24
+ * than inventing a route that would 404.
25
+ *
26
+ * Anything not in this table is not reachable by this server, and that is the same default-closed
27
+ * posture the server's own allow-list takes (`ContentManagementRouteScopes.RequiredScope` returns
28
+ * null for an unknown segment, which the filter treats as a refusal). Workflow, providers,
29
+ * environments, promotion and credential minting have no row because spec #641 admits none of them.
30
+ */
31
+ export const WRITABLE_KINDS = [
32
+ 'contract',
33
+ 'template',
34
+ 'component',
35
+ 'folder',
36
+ 'site',
37
+ 'node',
38
+ 'nodePayload',
39
+ 'adapter',
40
+ 'stream',
41
+ 'audience',
42
+ 'categoryGroup',
43
+ 'category',
44
+ ];
45
+ const ROUTES = {
46
+ contract: {
47
+ label: 'Contract',
48
+ create: '/contracts',
49
+ update: { method: 'PUT', path: '/contracts/{id}' },
50
+ remove: '/contracts/{id}',
51
+ readOne: '/contracts/{id}',
52
+ list: '/contracts',
53
+ },
54
+ template: {
55
+ label: 'Template',
56
+ create: '/templates',
57
+ update: { method: 'PUT', path: '/templates/{id}' },
58
+ remove: '/templates/{id}',
59
+ readOne: '/templates/{id}',
60
+ list: '/templates',
61
+ },
62
+ component: {
63
+ label: 'Component',
64
+ create: '/components',
65
+ update: { method: 'PUT', path: '/components/{id}' },
66
+ remove: '/components/{id}',
67
+ readOne: '/components/{id}',
68
+ list: '/components',
69
+ },
70
+ folder: {
71
+ label: 'Folder',
72
+ create: '/folders',
73
+ update: { method: 'PUT', path: '/folders/{id}' },
74
+ remove: '/folders/{id}',
75
+ readOne: null,
76
+ list: '/folders',
77
+ },
78
+ site: {
79
+ label: 'Site (an Experience root)',
80
+ create: '/experience/sites',
81
+ update: null,
82
+ remove: null,
83
+ readOne: null,
84
+ list: '/experience/sites',
85
+ },
86
+ node: {
87
+ label: 'Experience node (a page)',
88
+ create: '/experience/nodes',
89
+ update: { method: 'PUT', path: '/experience/nodes/{id}' },
90
+ remove: '/experience/nodes/{id}',
91
+ readOne: '/experience/nodes/{id}',
92
+ list: null,
93
+ },
94
+ nodePayload: {
95
+ label: "An Experience node's payload (what it renders)",
96
+ create: null,
97
+ update: { method: 'PUT', path: '/experience/nodes/{id}/payload' },
98
+ remove: '/experience/nodes/{id}/payload',
99
+ readOne: null,
100
+ list: null,
101
+ },
102
+ adapter: {
103
+ label: 'Adapter (a field mapping)',
104
+ create: '/adapters',
105
+ // PATCH, not PUT. See this file's own header.
106
+ update: { method: 'PATCH', path: '/adapters/{id}' },
107
+ remove: '/adapters/{id}',
108
+ readOne: '/adapters/{id}',
109
+ list: '/adapters',
110
+ },
111
+ stream: {
112
+ label: 'Stream (a saved query over published content)',
113
+ create: '/streams',
114
+ update: { method: 'PUT', path: '/streams/{id}' },
115
+ remove: '/streams/{id}',
116
+ readOne: '/streams/{id}',
117
+ list: '/streams',
118
+ },
119
+ audience: {
120
+ label: 'Audience (a personalization segment)',
121
+ create: '/audiences',
122
+ update: { method: 'PUT', path: '/audiences/{id}' },
123
+ remove: '/audiences/{id}',
124
+ readOne: null,
125
+ list: '/audiences',
126
+ },
127
+ categoryGroup: {
128
+ label: 'Category group',
129
+ create: '/taxonomy/groups',
130
+ update: { method: 'PUT', path: '/taxonomy/groups/{id}' },
131
+ remove: '/taxonomy/groups/{id}',
132
+ readOne: null,
133
+ list: '/taxonomy/groups',
134
+ },
135
+ category: {
136
+ label: 'Category',
137
+ create: '/taxonomy/categories',
138
+ update: { method: 'PUT', path: '/taxonomy/categories/{id}' },
139
+ remove: '/taxonomy/categories/{id}',
140
+ readOne: null,
141
+ list: null,
142
+ },
143
+ };
144
+ export function isEntityKind(value) {
145
+ return Object.hasOwn(ROUTES, value);
146
+ }
147
+ export function routesFor(kind) {
148
+ return ROUTES[kind];
149
+ }
150
+ /**
151
+ * Substitutes `{id}` in a path template.
152
+ *
153
+ * Encoded, because every id here is a Guid today and will not always be — a stream is addressable by
154
+ * external id on the delivery side already, and an id that ever carries a slash would otherwise
155
+ * silently change which route was matched.
156
+ */
157
+ export function withId(template, id) {
158
+ return template.replace('{id}', encodeURIComponent(id));
159
+ }
160
+ /**
161
+ * The message a kind this server cannot reach gets.
162
+ *
163
+ * It answers locally rather than sending the request to earn a `404`, because the `404` says only
164
+ * "no such route" — it does not say which kinds *are* writable, which is the one thing that gets the
165
+ * agent to its next call. This is the same instinct as §3's verbatim relay pointed the other way:
166
+ * be transparent about what the server knows, and say nothing it does not.
167
+ */
168
+ export function unknownKindMessage(kind) {
169
+ return (`Unknown kind "${kind}". This server can write: ${WRITABLE_KINDS.join(', ')}.\n` +
170
+ 'Workflows, providers, environments, promotion and credential minting are deliberately not ' +
171
+ 'reachable with a management key.');
172
+ }
173
+ //# sourceMappingURL=routes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routes.js","sourceRoot":"","sources":["../src/routes.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import { type ServerConfig } from './config.js';
3
+ import { type Session } from './session.js';
4
+ /**
5
+ * Assembly. Nothing here decides anything — which tools exist is decided by the key's own scopes
6
+ * (`session.has`), and which routes exist is decided by `routes.ts`. This file only wires them.
7
+ */
8
+ export declare const SERVER_NAME = "ebitex-content";
9
+ /** Kept in step with `package.json` by the build; reported in the MCP handshake. */
10
+ export declare const SERVER_VERSION = "0.1.0";
11
+ export type BuiltServer = {
12
+ server: McpServer;
13
+ session: Session;
14
+ /** What to print to stderr before connecting — see {@link startupBanner}. */
15
+ banner: string;
16
+ };
17
+ export declare function buildServer(options?: {
18
+ config?: ServerConfig;
19
+ fetchImpl?: typeof fetch;
20
+ }): Promise<BuiltServer>;
21
+ /**
22
+ * What the operator sees on stderr at startup.
23
+ *
24
+ * It exists for one failure, and it is not a bug in this server: a key bound to a production
25
+ * authoring environment sitting in an MCP client's config file, with an agent doing exactly what it
26
+ * was asked to. This server cannot detect that — whether an environment is "production" is the
27
+ * customer's own topology, and a management key deliberately cannot see it — so saying plainly
28
+ * where writes will land is the whole mitigation, and it is why it names the environment rather
29
+ * than only reporting that the key worked.
30
+ */
31
+ export declare function startupBanner(config: ServerConfig, session: Session): string;
32
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAA;AAEnE,OAAO,EAAc,KAAK,YAAY,EAAE,MAAM,aAAa,CAAA;AAE3D,OAAO,EAAmC,KAAK,OAAO,EAAE,MAAM,cAAc,CAAA;AAG5E;;;GAGG;AAEH,eAAO,MAAM,WAAW,mBAAmB,CAAA;AAE3C,oFAAoF;AACpF,eAAO,MAAM,cAAc,UAAU,CAAA;AAErC,MAAM,MAAM,WAAW,GAAG;IACxB,MAAM,EAAE,SAAS,CAAA;IACjB,OAAO,EAAE,OAAO,CAAA;IAChB,6EAA6E;IAC7E,MAAM,EAAE,MAAM,CAAA;CACf,CAAA;AAED,wBAAsB,WAAW,CAAC,OAAO,CAAC,EAAE;IAC1C,MAAM,CAAC,EAAE,YAAY,CAAA;IACrB,SAAS,CAAC,EAAE,OAAO,KAAK,CAAA;CACzB,GAAG,OAAO,CAAC,WAAW,CAAC,CA4BvB;AAED;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,YAAY,EAAE,OAAO,EAAE,OAAO,GAAG,MAAM,CAoB5E"}
package/dist/server.js ADDED
@@ -0,0 +1,65 @@
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import { createClient } from './client.js';
3
+ import { readConfig } from './config.js';
4
+ import { registerResources } from './resources/register.js';
5
+ import { resolveSession, SCOPE_AUTHORING } from './session.js';
6
+ import { registerTools } from './tools/register.js';
7
+ /**
8
+ * Assembly. Nothing here decides anything — which tools exist is decided by the key's own scopes
9
+ * (`session.has`), and which routes exist is decided by `routes.ts`. This file only wires them.
10
+ */
11
+ export const SERVER_NAME = 'ebitex-content';
12
+ /** Kept in step with `package.json` by the build; reported in the MCP handshake. */
13
+ export const SERVER_VERSION = '0.1.0';
14
+ export async function buildServer(options) {
15
+ const config = options?.config ?? readConfig();
16
+ const client = createClient({ baseUrl: config.baseUrl, key: config.key, fetchImpl: options?.fetchImpl });
17
+ const target = config.targetKey
18
+ ? createClient({ baseUrl: config.baseUrl, key: config.targetKey, fetchImpl: options?.fetchImpl })
19
+ : null;
20
+ const session = await resolveSession(client, { readOnlyRequested: config.readOnly });
21
+ const server = new McpServer({ name: SERVER_NAME, version: SERVER_VERSION }, {
22
+ instructions: 'Content is ebitex\'s CMS. Start with content_describe — it returns every field type with ' +
23
+ 'its own settings schema and the Contracts and Templates this environment already has, ' +
24
+ 'which is where the shape of anything you write comes from. Read the ' +
25
+ 'ebitex-content://help/agent-authoring resource before building a model; it explains what ' +
26
+ 'Contracts, Templates, Presentations, Adapters and the Experience tree are for, and the ' +
27
+ 'order to create them in. When a write is refused, the refusal names the failing field: ' +
28
+ 'correct that one thing and call again.',
29
+ });
30
+ registerTools(server, { client, session, target });
31
+ registerResources(server, { client, session });
32
+ return { server, session, banner: startupBanner(config, session) };
33
+ }
34
+ /**
35
+ * What the operator sees on stderr at startup.
36
+ *
37
+ * It exists for one failure, and it is not a bug in this server: a key bound to a production
38
+ * authoring environment sitting in an MCP client's config file, with an agent doing exactly what it
39
+ * was asked to. This server cannot detect that — whether an environment is "production" is the
40
+ * customer's own topology, and a management key deliberately cannot see it — so saying plainly
41
+ * where writes will land is the whole mitigation, and it is why it names the environment rather
42
+ * than only reporting that the key worked.
43
+ */
44
+ export function startupBanner(config, session) {
45
+ const { who } = session;
46
+ const lines = [
47
+ 'ebitex Content MCP',
48
+ ` api ${config.baseUrl}`,
49
+ ` organization ${who.organizationName ?? who.organizationId}`,
50
+ ` environment ${who.environmentName ?? who.environmentId}`,
51
+ ` acting as ${who.roleName ?? 'unknown role'} (key: ${who.keyName ?? 'unnamed'})`,
52
+ ` scopes ${who.scopes.length ? who.scopes.join(', ') : 'none'}`,
53
+ ];
54
+ if (config.readOnly) {
55
+ lines.push(' mode read-only (forced by EBITEX_CONTENT_MCP_READ_ONLY)');
56
+ }
57
+ else if (session.has(SCOPE_AUTHORING)) {
58
+ lines.push(` mode READ-WRITE — writes land in "${who.environmentName ?? who.environmentId}"`);
59
+ }
60
+ else {
61
+ lines.push(' mode read-only (this key carries no authoring scope)');
62
+ }
63
+ return lines.join('\n');
64
+ }
65
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,45 @@
1
+ import type { ContentClient } from './client.js';
2
+ /**
3
+ * Who this key is, resolved once at startup from `GET /whoami` — SPEC.md's Business Logic §4 and §6.
4
+ *
5
+ * Two things depend on it, and they are the reason that endpoint was added by this spec rather than
6
+ * worked around:
7
+ *
8
+ * - **Which tools exist at all.** A key's scopes decide what it may do, and an agent that cannot
9
+ * see a tool will not plan around it. Advertising a write tool a read-scoped key holds is an
10
+ * expensive way to learn something knowable before the session began — the agent spends a turn,
11
+ * reads a `403`, and has to re-plan.
12
+ * - **Where writes are landing.** The realistic failure of a write-capable agent tool is not a bug
13
+ * in it; it is a key bound to a production environment sitting in a config file somebody else
14
+ * wrote. The server cannot detect that (see §6 — production-ness is the customer's own topology,
15
+ * and #641 deliberately keeps the environments family off a key), so the mitigation is to say
16
+ * plainly what the key is bound to, at startup and on every write.
17
+ */
18
+ export declare const SCOPE_READ = "content.management.read";
19
+ export declare const SCOPE_WRITE = "content.management.write";
20
+ export declare const SCOPE_PUBLISH = "content.management.publish";
21
+ export declare const SCOPE_AUTHORING = "content.management.authoring";
22
+ export type WhoAmI = {
23
+ organizationId: string;
24
+ organizationName: string | null;
25
+ organizationSlug: string | null;
26
+ environmentId: string;
27
+ environmentName: string | null;
28
+ roleName: string | null;
29
+ keyName: string | null;
30
+ scopes: string[];
31
+ };
32
+ export type Session = {
33
+ who: WhoAmI;
34
+ /** True when the operator forced read-only regardless of what the key could do. */
35
+ readOnlyRequested: boolean;
36
+ has(scope: string): boolean;
37
+ /** One line naming where a write just landed, appended to every write result (§6). */
38
+ contextLine(): string;
39
+ };
40
+ export declare class StartupError extends Error {
41
+ }
42
+ export declare function resolveSession(client: ContentClient, options: {
43
+ readOnlyRequested: boolean;
44
+ }): Promise<Session>;
45
+ //# sourceMappingURL=session.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAGhD;;;;;;;;;;;;;;;GAeG;AAEH,eAAO,MAAM,UAAU,4BAA4B,CAAA;AACnD,eAAO,MAAM,WAAW,6BAA6B,CAAA;AACrD,eAAO,MAAM,aAAa,+BAA+B,CAAA;AACzD,eAAO,MAAM,eAAe,iCAAiC,CAAA;AAE7D,MAAM,MAAM,MAAM,GAAG;IACnB,cAAc,EAAE,MAAM,CAAA;IACtB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAA;IAC/B,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAA;IAC/B,aAAa,EAAE,MAAM,CAAA;IACrB,eAAe,EAAE,MAAM,GAAG,IAAI,CAAA;IAC9B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,MAAM,EAAE,MAAM,EAAE,CAAA;CACjB,CAAA;AAED,MAAM,MAAM,OAAO,GAAG;IACpB,GAAG,EAAE,MAAM,CAAA;IACX,mFAAmF;IACnF,iBAAiB,EAAE,OAAO,CAAA;IAC1B,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAA;IAC3B,sFAAsF;IACtF,WAAW,IAAI,MAAM,CAAA;CACtB,CAAA;AAED,qBAAa,YAAa,SAAQ,KAAK;CAAG;AAE1C,wBAAsB,cAAc,CAClC,MAAM,EAAE,aAAa,EACrB,OAAO,EAAE;IAAE,iBAAiB,EAAE,OAAO,CAAA;CAAE,GACtC,OAAO,CAAC,OAAO,CAAC,CAmBlB"}
@@ -0,0 +1,71 @@
1
+ import { ContentApiError } from './errors.js';
2
+ /**
3
+ * Who this key is, resolved once at startup from `GET /whoami` — SPEC.md's Business Logic §4 and §6.
4
+ *
5
+ * Two things depend on it, and they are the reason that endpoint was added by this spec rather than
6
+ * worked around:
7
+ *
8
+ * - **Which tools exist at all.** A key's scopes decide what it may do, and an agent that cannot
9
+ * see a tool will not plan around it. Advertising a write tool a read-scoped key holds is an
10
+ * expensive way to learn something knowable before the session began — the agent spends a turn,
11
+ * reads a `403`, and has to re-plan.
12
+ * - **Where writes are landing.** The realistic failure of a write-capable agent tool is not a bug
13
+ * in it; it is a key bound to a production environment sitting in a config file somebody else
14
+ * wrote. The server cannot detect that (see §6 — production-ness is the customer's own topology,
15
+ * and #641 deliberately keeps the environments family off a key), so the mitigation is to say
16
+ * plainly what the key is bound to, at startup and on every write.
17
+ */
18
+ export const SCOPE_READ = 'content.management.read';
19
+ export const SCOPE_WRITE = 'content.management.write';
20
+ export const SCOPE_PUBLISH = 'content.management.publish';
21
+ export const SCOPE_AUTHORING = 'content.management.authoring';
22
+ export class StartupError extends Error {
23
+ }
24
+ export async function resolveSession(client, options) {
25
+ let who;
26
+ try {
27
+ who = (await client.request('GET', '/whoami'));
28
+ }
29
+ catch (error) {
30
+ throw new StartupError(startupMessage(error, client.baseUrl));
31
+ }
32
+ const scopes = new Set(who.scopes ?? []);
33
+ return {
34
+ who,
35
+ readOnlyRequested: options.readOnlyRequested,
36
+ // A forced read-only session reports every write scope as absent, so tool registration —
37
+ // which asks this and nothing else — needs no second concept of "but the operator said no".
38
+ has: (scope) => (options.readOnlyRequested && isWriteScope(scope) ? false : scopes.has(scope)),
39
+ contextLine: () => `[${who.organizationName ?? who.organizationId} · ${who.environmentName ?? who.environmentId} · as ${who.roleName ?? 'unknown role'}]`,
40
+ };
41
+ }
42
+ function isWriteScope(scope) {
43
+ return scope === SCOPE_WRITE || scope === SCOPE_PUBLISH || scope === SCOPE_AUTHORING;
44
+ }
45
+ /**
46
+ * What a failed startup says.
47
+ *
48
+ * Each arm names a **different remedy**, which is the only reason to distinguish them at all: a
49
+ * `401` means the key string is wrong, a `403 tier_required` means nothing about the key is wrong
50
+ * and somebody has to change the plan, and a `404` means this API predates `/whoami` entirely.
51
+ * Collapsing them into "could not connect" would leave the reader guessing between three unrelated
52
+ * actions.
53
+ */
54
+ function startupMessage(error, baseUrl) {
55
+ if (!(error instanceof ContentApiError)) {
56
+ return (`Could not reach the Content Management API at ${baseUrl}.\n` +
57
+ (error instanceof Error ? error.message : String(error)));
58
+ }
59
+ if (error.status === 401) {
60
+ return `The Content management key was not accepted by ${baseUrl} (${error.code ?? 'unauthorized'}).`;
61
+ }
62
+ if (error.status === 404) {
63
+ return (`${baseUrl} does not serve GET /content/management/v1/whoami, which this server needs in ` +
64
+ 'order to know which organization and environment the key is bound to, and which tools to ' +
65
+ 'offer. Upgrade the API, or point EBITEX_CONTENT_API_BASE at one that has it.');
66
+ }
67
+ // Everything else — tier, lapsed payment, the Content app not enabled, an IP allow-list — is a
68
+ // real refusal with a real message, and relaying it beats classifying it (§3).
69
+ return `The Content Management API refused this key.\n${error.message}`;
70
+ }
71
+ //# sourceMappingURL=session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.js","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAE7C;;;;;;;;;;;;;;;GAeG;AAEH,MAAM,CAAC,MAAM,UAAU,GAAG,yBAAyB,CAAA;AACnD,MAAM,CAAC,MAAM,WAAW,GAAG,0BAA0B,CAAA;AACrD,MAAM,CAAC,MAAM,aAAa,GAAG,4BAA4B,CAAA;AACzD,MAAM,CAAC,MAAM,eAAe,GAAG,8BAA8B,CAAA;AAsB7D,MAAM,OAAO,YAAa,SAAQ,KAAK;CAAG;AAE1C,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,MAAqB,EACrB,OAAuC;IAEvC,IAAI,GAAW,CAAA;IACf,IAAI,CAAC;QACH,GAAG,GAAG,CAAC,MAAM,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,SAAS,CAAC,CAAW,CAAA;IAC1D,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,YAAY,CAAC,cAAc,CAAC,KAAK,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC,CAAA;IAC/D,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,MAAM,IAAI,EAAE,CAAC,CAAA;IAExC,OAAO;QACL,GAAG;QACH,iBAAiB,EAAE,OAAO,CAAC,iBAAiB;QAC5C,yFAAyF;QACzF,4FAA4F;QAC5F,GAAG,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,iBAAiB,IAAI,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAC9F,WAAW,EAAE,GAAG,EAAE,CAChB,IAAI,GAAG,CAAC,gBAAgB,IAAI,GAAG,CAAC,cAAc,MAAM,GAAG,CAAC,eAAe,IAAI,GAAG,CAAC,aAAa,SAAS,GAAG,CAAC,QAAQ,IAAI,cAAc,GAAG;KACzI,CAAA;AACH,CAAC;AAED,SAAS,YAAY,CAAC,KAAa;IACjC,OAAO,KAAK,KAAK,WAAW,IAAI,KAAK,KAAK,aAAa,IAAI,KAAK,KAAK,eAAe,CAAA;AACtF,CAAC;AAED;;;;;;;;GAQG;AACH,SAAS,cAAc,CAAC,KAAc,EAAE,OAAe;IACrD,IAAI,CAAC,CAAC,KAAK,YAAY,eAAe,CAAC,EAAE,CAAC;QACxC,OAAO,CACL,iDAAiD,OAAO,KAAK;YAC7D,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CACzD,CAAA;IACH,CAAC;IAED,IAAI,KAAK,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;QACzB,OAAO,kDAAkD,OAAO,KAAK,KAAK,CAAC,IAAI,IAAI,cAAc,IAAI,CAAA;IACvG,CAAC;IAED,IAAI,KAAK,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;QACzB,OAAO,CACL,GAAG,OAAO,gFAAgF;YAC1F,2FAA2F;YAC3F,8EAA8E,CAC/E,CAAA;IACH,CAAC;IAED,+FAA+F;IAC/F,+EAA+E;IAC/E,OAAO,iDAAiD,KAAK,CAAC,OAAO,EAAE,CAAA;AACzE,CAAC"}
@@ -0,0 +1,26 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import type { ContentClient } from '../client.js';
3
+ import { type Session } from '../session.js';
4
+ /**
5
+ * The eight tools — SPEC.md's Architecture table.
6
+ *
7
+ * They are **task-shaped**, not endpoint-shaped: one per thing an agent does, never one per REST
8
+ * route or per entity kind. With the per-entity surface admitted the API is roughly thirty endpoint
9
+ * groups, so a generated one-tool-per-route surface would crowd an agent's context with dozens of
10
+ * entries to express eight tasks — which is why §8 rejects generating from OpenAPI, and why the
11
+ * case against it got *stronger* as the API grew rather than weaker.
12
+ *
13
+ * The payloads are deliberately opaque. `content_write` takes a `kind` and an object, and this
14
+ * module has no idea what belongs in that object: the agent learns each Contract's shape from
15
+ * `content_describe` at runtime, and the server validates what arrives. A per-kind tool schema
16
+ * would be a second copy of the content model living here, stale the first time a FieldType ships —
17
+ * the precise drift §1 exists to prevent.
18
+ */
19
+ export type ToolContext = {
20
+ client: ContentClient;
21
+ session: Session;
22
+ /** The credential for the environment `content_transfer` imports into, when one is configured. */
23
+ target: ContentClient | null;
24
+ };
25
+ export declare function registerTools(server: McpServer, context: ToolContext): void;
26
+ //# sourceMappingURL=register.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"register.d.ts","sourceRoot":"","sources":["../../src/tools/register.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAA;AAExE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAGjD,OAAO,EAA2D,KAAK,OAAO,EAAE,MAAM,eAAe,CAAA;AAGrG;;;;;;;;;;;;;;GAcG;AAEH,MAAM,MAAM,WAAW,GAAG;IACxB,MAAM,EAAE,aAAa,CAAA;IACrB,OAAO,EAAE,OAAO,CAAA;IAChB,kGAAkG;IAClG,MAAM,EAAE,aAAa,GAAG,IAAI,CAAA;CAC7B,CAAA;AAID,wBAAgB,aAAa,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,WAAW,GAAG,IAAI,CA0R3E"}