@absolutejs/mcp 0.4.2 → 0.5.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.
- package/README.md +43 -0
- package/dist/index.js +261 -9
- package/dist/manifest.js +8606 -0
- package/dist/manifest.json +124 -0
- package/dist/src/index.d.ts +2 -1
- package/dist/src/jsonrpc.d.ts +2 -1
- package/dist/src/manifest.d.ts +2 -0
- package/dist/src/tasks.d.ts +14 -0
- package/dist/src/types.d.ts +53 -0
- package/package.json +23 -2
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
{
|
|
2
|
+
"contract": 2,
|
|
3
|
+
"identity": {
|
|
4
|
+
"accent": "#0ea5e9",
|
|
5
|
+
"category": "ai",
|
|
6
|
+
"description": "Serve a remote Model Context Protocol endpoint with OAuth discovery, agency action enforcement, approval receipts, and caller-bound durable Tasks. Bridge installed AbsoluteJS packages' manifests with `toMcpToolRegistry` and enforce their declared effects before execution.",
|
|
7
|
+
"docsUrl": "https://github.com/absolutejs/mcp",
|
|
8
|
+
"name": "@absolutejs/mcp",
|
|
9
|
+
"tagline": "Let AI assistants connect to your site and use its tools."
|
|
10
|
+
},
|
|
11
|
+
"requires": {
|
|
12
|
+
"peers": [
|
|
13
|
+
{
|
|
14
|
+
"name": "elysia",
|
|
15
|
+
"range": ">=1.1.0",
|
|
16
|
+
"reason": "plugin host"
|
|
17
|
+
}
|
|
18
|
+
]
|
|
19
|
+
},
|
|
20
|
+
"settings": {
|
|
21
|
+
"type": "object",
|
|
22
|
+
"required": [
|
|
23
|
+
"issuer",
|
|
24
|
+
"path"
|
|
25
|
+
],
|
|
26
|
+
"properties": {
|
|
27
|
+
"instructions": {
|
|
28
|
+
"description": "A short note shown to the AI about what this server does and how to use it.",
|
|
29
|
+
"title": "Instructions for the AI",
|
|
30
|
+
"type": "string"
|
|
31
|
+
},
|
|
32
|
+
"issuer": {
|
|
33
|
+
"description": "The web address of the sign-in server that issues access tokens for this endpoint. Usually your site's own address.",
|
|
34
|
+
"examples": [
|
|
35
|
+
"https://yoursite.com"
|
|
36
|
+
],
|
|
37
|
+
"format": "uri",
|
|
38
|
+
"title": "Token issuer",
|
|
39
|
+
"type": "string"
|
|
40
|
+
},
|
|
41
|
+
"path": {
|
|
42
|
+
"default": "/mcp",
|
|
43
|
+
"description": "Where on your site the AI endpoint lives.",
|
|
44
|
+
"title": "Endpoint path",
|
|
45
|
+
"type": "string"
|
|
46
|
+
},
|
|
47
|
+
"scopesSupported": {
|
|
48
|
+
"description": "The permission scopes this endpoint advertises to connecting clients.",
|
|
49
|
+
"examples": [
|
|
50
|
+
[
|
|
51
|
+
"openid",
|
|
52
|
+
"mcp"
|
|
53
|
+
]
|
|
54
|
+
],
|
|
55
|
+
"title": "Advertised scopes",
|
|
56
|
+
"x-group": "advanced",
|
|
57
|
+
"type": "array",
|
|
58
|
+
"items": {
|
|
59
|
+
"type": "string"
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
"serveRootMetadata": {
|
|
63
|
+
"description": "Also answer discovery requests at the site root. Turn on for exactly one endpoint per site.",
|
|
64
|
+
"title": "Answer root discovery",
|
|
65
|
+
"x-group": "advanced",
|
|
66
|
+
"type": "boolean"
|
|
67
|
+
},
|
|
68
|
+
"serverInfo": {
|
|
69
|
+
"description": "How this server introduces itself to connecting AI clients.",
|
|
70
|
+
"title": "Server identity",
|
|
71
|
+
"type": "object",
|
|
72
|
+
"properties": {
|
|
73
|
+
"name": {
|
|
74
|
+
"title": "Machine name",
|
|
75
|
+
"examples": [
|
|
76
|
+
"your-site"
|
|
77
|
+
],
|
|
78
|
+
"type": "string"
|
|
79
|
+
},
|
|
80
|
+
"title": {
|
|
81
|
+
"title": "Display name",
|
|
82
|
+
"examples": [
|
|
83
|
+
"Your Site"
|
|
84
|
+
],
|
|
85
|
+
"type": "string"
|
|
86
|
+
},
|
|
87
|
+
"version": {
|
|
88
|
+
"title": "Version",
|
|
89
|
+
"examples": [
|
|
90
|
+
"1.0.0"
|
|
91
|
+
],
|
|
92
|
+
"type": "string"
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
"wiring": [
|
|
99
|
+
{
|
|
100
|
+
"description": "Mount a remote MCP endpoint that serves the tools of installed AbsoluteJS packages — bridge each package's manifest and any MCP client (Claude, etc.) can call them.",
|
|
101
|
+
"id": "default",
|
|
102
|
+
"server": {
|
|
103
|
+
"code": ".use(\n\tmcpServer({\n\t\t// TODO: decide who may call this endpoint — see verifyBearer for\n\t\t// the standard OAuth bearer-token checks. Denies everyone until\n\t\t// you wire it.\n\t\tauthorize: async () => ({\n\t\t\tok: false,\n\t\t\treason: 'authorization not configured'\n\t\t}),\n\t\tinstructions: ${settings.instructions},\n\t\tissuer: ${settings.issuer},\n\t\tpath: ${settings.path},\n\t\tscopesSupported: ${settings.scopesSupported},\n\t\tserveRootMetadata: ${settings.serveRootMetadata},\n\t\tserverInfo: ${settings.serverInfo} ?? { name: 'my-site', version: '0.1.0' },\n\t\ttools: async () => {\n\t\t\t// Every installed AbsoluteJS package ships a manifest; bridging\n\t\t\t// it exposes that package's tools here. Pass the live instance\n\t\t\t// you constructed for the package as `runtime` — tools without\n\t\t\t// their binding are omitted (fail closed).\n\t\t\t// TODO: list the packages this endpoint should expose.\n\t\t\tconst exposed: { name: string; runtime?: unknown }[] = [];\n\t\t\tconst registries = await Promise.all(\n\t\t\t\texposed.map(async ({ name, runtime }) => {\n\t\t\t\t\tconst loaded = await loadManifest(name);\n\n\t\t\t\t\treturn loaded.ok\n\t\t\t\t\t\t? toMcpToolRegistry(loaded.manifest, { runtime })\n\t\t\t\t\t\t: {};\n\t\t\t\t})\n\t\t\t);\n\n\t\t\treturn Object.assign({}, ...registries);\n\t\t}\n\t})\n)",
|
|
104
|
+
"imports": [
|
|
105
|
+
{
|
|
106
|
+
"from": "@absolutejs/mcp",
|
|
107
|
+
"names": [
|
|
108
|
+
"mcpServer"
|
|
109
|
+
]
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
"from": "@absolutejs/manifest",
|
|
113
|
+
"names": [
|
|
114
|
+
"loadManifest",
|
|
115
|
+
"toMcpToolRegistry"
|
|
116
|
+
]
|
|
117
|
+
}
|
|
118
|
+
],
|
|
119
|
+
"placement": "server-plugin"
|
|
120
|
+
},
|
|
121
|
+
"title": "Serve installed packages' tools over MCP"
|
|
122
|
+
}
|
|
123
|
+
]
|
|
124
|
+
}
|
package/dist/src/index.d.ts
CHANGED
|
@@ -38,4 +38,5 @@ export { createMcpHandler } from "./handler";
|
|
|
38
38
|
export { metadataPathFor, protectedResourceMetadata, type ProtectedResourceMetadata, } from "./metadata";
|
|
39
39
|
export { mcpServer } from "./server";
|
|
40
40
|
export { createSessionRegistry, type SessionRegistry } from "./sessions";
|
|
41
|
-
export
|
|
41
|
+
export { createMemoryMcpTaskStore, publicMcpTask } from "./tasks";
|
|
42
|
+
export type { McpAgencyOptions, McpAudioContent, McpElicitAnswer, McpElicitationRequest, McpElicitBus, McpElicitResult, McpSessionStore, McpAuthResult, McpCallGate, McpCallMeta, McpContent, McpImageContent, McpPromptArgument, McpPromptDefinition, McpPrompts, McpResource, McpResourceLink, McpResources, McpServerConfig, McpServerInfo, McpTextContent, McpTask, McpTaskStatus, McpTaskStore, McpTasksOptions, McpTool, McpToolAnnotations, McpToolCallContext, McpToolContext, McpToolRegistry, McpToolResult, McpToolReturn, } from "./types";
|
package/dist/src/jsonrpc.d.ts
CHANGED
|
@@ -3,13 +3,14 @@ export declare const JSONRPC_INVALID_REQUEST = -32600;
|
|
|
3
3
|
export declare const JSONRPC_METHOD_NOT_FOUND = -32601;
|
|
4
4
|
export declare const JSONRPC_INVALID_PARAMS = -32602;
|
|
5
5
|
export declare const JSONRPC_INTERNAL_ERROR = -32603;
|
|
6
|
+
export declare const JSONRPC_MISSING_REQUIRED_CLIENT_CAPABILITY = -32003;
|
|
6
7
|
export declare const HTTP_ACCEPTED = 202;
|
|
7
8
|
export declare const HTTP_NO_CONTENT = 204;
|
|
8
9
|
export declare const HTTP_UNAUTHORIZED = 401;
|
|
9
10
|
export declare const HTTP_METHOD_NOT_ALLOWED = 405;
|
|
10
11
|
export type JsonRpcId = string | number | null;
|
|
11
12
|
export declare const rpcResult: (id: JsonRpcId, result: unknown) => Response;
|
|
12
|
-
export declare const rpcError: (id: JsonRpcId, code: number, message: string) => Response;
|
|
13
|
+
export declare const rpcError: (id: JsonRpcId, code: number, message: string, data?: Record<string, unknown>) => Response;
|
|
13
14
|
export declare const notificationAck: () => Response;
|
|
14
15
|
/** 401 with the RFC 9728 `WWW-Authenticate` challenge pointing at the
|
|
15
16
|
* protected-resource metadata, so the client can discover the auth server. */
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { McpTask, McpTaskStore } from "./types";
|
|
2
|
+
export declare const createMemoryMcpTaskStore: () => McpTaskStore;
|
|
3
|
+
export declare const publicMcpTask: ({ authorizationKey, ...task }: McpTask) => {
|
|
4
|
+
createdAt: string;
|
|
5
|
+
error?: Record<string, unknown>;
|
|
6
|
+
inputRequests?: Record<string, unknown>;
|
|
7
|
+
lastUpdatedAt: string;
|
|
8
|
+
pollIntervalMs?: number;
|
|
9
|
+
result?: Record<string, unknown>;
|
|
10
|
+
status: import("./types").McpTaskStatus;
|
|
11
|
+
statusMessage?: string;
|
|
12
|
+
taskId: string;
|
|
13
|
+
ttlMs: number | null;
|
|
14
|
+
};
|
package/dist/src/types.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { Agency, AgentActor } from "@absolutejs/agency";
|
|
2
|
+
import type { ToolAuthorization } from "@absolutejs/manifest";
|
|
1
3
|
/** MCP behaviour hints, passed straight through to the client on `tools/list`.
|
|
2
4
|
* Structurally identical to `@absolutejs/ai`'s `AIToolAnnotations`, so a tool
|
|
3
5
|
* map from that package satisfies this without conversion. All optional. */
|
|
@@ -108,6 +110,9 @@ export type McpToolCallContext = {
|
|
|
108
110
|
/** One callable tool. `inputSchema` is a JSON Schema object. */
|
|
109
111
|
export type McpTool = {
|
|
110
112
|
annotations?: McpToolAnnotations;
|
|
113
|
+
/** Enforceable semantic effects from manifest contract 2. A tool carrying
|
|
114
|
+
* this is hidden unless the server configures `agency`. */
|
|
115
|
+
authorization?: ToolAuthorization;
|
|
111
116
|
description: string;
|
|
112
117
|
handler: (args: unknown, context: McpToolCallContext) => McpToolReturn | Promise<McpToolReturn>;
|
|
113
118
|
inputSchema: Record<string, unknown>;
|
|
@@ -165,6 +170,50 @@ export type McpToolContext<Caller> = {
|
|
|
165
170
|
caller: Caller;
|
|
166
171
|
meta: McpCallMeta;
|
|
167
172
|
};
|
|
173
|
+
export type McpAgencyOptions<Caller> = {
|
|
174
|
+
enforcement: Agency;
|
|
175
|
+
resolveActor: (context: {
|
|
176
|
+
caller: Caller;
|
|
177
|
+
scopes: string[];
|
|
178
|
+
}) => Promise<AgentActor> | AgentActor;
|
|
179
|
+
serverId?: string;
|
|
180
|
+
};
|
|
181
|
+
export type McpTaskStatus = "cancelled" | "completed" | "failed" | "input_required" | "working";
|
|
182
|
+
export type McpTask = {
|
|
183
|
+
authorizationKey: string;
|
|
184
|
+
createdAt: string;
|
|
185
|
+
error?: Record<string, unknown>;
|
|
186
|
+
inputRequests?: Record<string, unknown>;
|
|
187
|
+
lastUpdatedAt: string;
|
|
188
|
+
pollIntervalMs?: number;
|
|
189
|
+
result?: Record<string, unknown>;
|
|
190
|
+
status: McpTaskStatus;
|
|
191
|
+
statusMessage?: string;
|
|
192
|
+
taskId: string;
|
|
193
|
+
ttlMs: number | null;
|
|
194
|
+
};
|
|
195
|
+
export type McpTaskStore = {
|
|
196
|
+
cancel: (taskId: string) => Promise<void> | void;
|
|
197
|
+
get: (taskId: string) => Promise<McpTask | null> | McpTask | null;
|
|
198
|
+
save: (task: McpTask) => Promise<void> | void;
|
|
199
|
+
update: (taskId: string, update: Partial<Omit<McpTask, "authorizationKey" | "createdAt" | "taskId">>) => Promise<McpTask | null> | McpTask | null;
|
|
200
|
+
};
|
|
201
|
+
export type McpTasksOptions<Caller> = {
|
|
202
|
+
authorizationKey: (caller: Caller) => Promise<string> | string;
|
|
203
|
+
onUpdate?: (context: {
|
|
204
|
+
caller: Caller;
|
|
205
|
+
inputResponses: Record<string, unknown>;
|
|
206
|
+
task: McpTask;
|
|
207
|
+
}) => Promise<void> | void;
|
|
208
|
+
pollIntervalMs?: number;
|
|
209
|
+
shouldCreate: (context: {
|
|
210
|
+
args: unknown;
|
|
211
|
+
caller: Caller;
|
|
212
|
+
name: string;
|
|
213
|
+
}) => Promise<boolean> | boolean;
|
|
214
|
+
store: McpTaskStore;
|
|
215
|
+
ttlMs?: number | null;
|
|
216
|
+
};
|
|
168
217
|
export type McpPrompts<Caller> = {
|
|
169
218
|
definitions: Record<string, McpPromptDefinition>;
|
|
170
219
|
get: (ctx: {
|
|
@@ -190,6 +239,8 @@ export type McpServerInfo = {
|
|
|
190
239
|
version: string;
|
|
191
240
|
};
|
|
192
241
|
export type McpServerConfig<Caller> = {
|
|
242
|
+
/** Per-tool action policy enforcement, approval, leases, and receipts. */
|
|
243
|
+
agency?: McpAgencyOptions<Caller>;
|
|
193
244
|
/** Resolve the request into a caller, or a reason for the 401. The package
|
|
194
245
|
* emits the 401 + RFC 9728 `WWW-Authenticate` challenge; you decide who is
|
|
195
246
|
* allowed in. See {@link verifyBearer} for the standard token checks. */
|
|
@@ -244,6 +295,8 @@ export type McpServerConfig<Caller> = {
|
|
|
244
295
|
/** Protocol versions this endpoint accepts; the first is the preferred one.
|
|
245
296
|
* Defaults to the versions this package knows. */
|
|
246
297
|
supportedProtocols?: string[];
|
|
298
|
+
/** Final SEP-2663 `io.modelcontextprotocol/tasks` extension support. */
|
|
299
|
+
tasks?: McpTasksOptions<Caller>;
|
|
247
300
|
/** Build the tool registry for this caller. Called once per request. */
|
|
248
301
|
tools: (ctx: McpToolContext<Caller>) => McpToolRegistry | Promise<McpToolRegistry>;
|
|
249
302
|
};
|
package/package.json
CHANGED
|
@@ -10,7 +10,28 @@
|
|
|
10
10
|
"peerDependencies": {
|
|
11
11
|
"elysia": ">=1.1.0"
|
|
12
12
|
},
|
|
13
|
+
"dependencies": {
|
|
14
|
+
"@absolutejs/agency": "^0.1.0",
|
|
15
|
+
"@absolutejs/manifest": "^0.2.0",
|
|
16
|
+
"@sinclair/typebox": "^0.34.0"
|
|
17
|
+
},
|
|
13
18
|
"license": "BUSL-1.1",
|
|
19
|
+
"absolutejs": {
|
|
20
|
+
"manifestContract": 2
|
|
21
|
+
},
|
|
22
|
+
"exports": {
|
|
23
|
+
".": {
|
|
24
|
+
"types": "./dist/src/index.d.ts",
|
|
25
|
+
"import": "./dist/index.js",
|
|
26
|
+
"default": "./dist/index.js"
|
|
27
|
+
},
|
|
28
|
+
"./manifest": {
|
|
29
|
+
"types": "./dist/src/manifest.d.ts",
|
|
30
|
+
"import": "./dist/manifest.js",
|
|
31
|
+
"default": "./dist/manifest.js"
|
|
32
|
+
},
|
|
33
|
+
"./manifest.json": "./dist/manifest.json"
|
|
34
|
+
},
|
|
14
35
|
"publishConfig": {
|
|
15
36
|
"access": "public"
|
|
16
37
|
},
|
|
@@ -30,12 +51,12 @@
|
|
|
30
51
|
"LICENSE"
|
|
31
52
|
],
|
|
32
53
|
"scripts": {
|
|
33
|
-
"build": "rm -rf dist && bun build src/index.ts --outdir dist --target=bun --external elysia && tsc --emitDeclarationOnly --project tsconfig.json",
|
|
54
|
+
"build": "rm -rf dist && bun build src/index.ts src/manifest.ts --outdir dist --root ./src --target=bun --external elysia && tsc --emitDeclarationOnly --project tsconfig.json && absolute-manifest emit",
|
|
34
55
|
"format": "prettier --write \"./**/*.{ts,json,md}\"",
|
|
35
56
|
"release": "bun run format && bun run test && bun run build && bun publish",
|
|
36
57
|
"test": "bun test",
|
|
37
58
|
"typecheck": "tsc --noEmit --project tsconfig.json"
|
|
38
59
|
},
|
|
39
60
|
"types": "./dist/src/index.d.ts",
|
|
40
|
-
"version": "0.
|
|
61
|
+
"version": "0.5.0"
|
|
41
62
|
}
|