@usegraft/mcp 0.1.0 → 0.2.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 +53 -0
- package/dist/index.d.ts +53 -3
- package/dist/index.js +760 -627
- package/package.json +24 -10
package/README.md
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# @usegraft/mcp
|
|
2
|
+
|
|
3
|
+
> An MCP server over your content, schema, and typed functions, with errors an agent can act on.
|
|
4
|
+
|
|
5
|
+
Part of [Graft](https://github.com/AndersonDesign1/graft), a CMS built so an AI agent is the primary operator.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm i @usegraft/mcp
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Serve on stdio
|
|
14
|
+
|
|
15
|
+
For `.mcp.json` and local agents. `graft mcp` does this for you.
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
import { createGraftMcp, serveStdio } from "@usegraft/mcp";
|
|
19
|
+
|
|
20
|
+
const server = createGraftMcp({ contentDir, collections, functions, db });
|
|
21
|
+
await serveStdio(server);
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Serve over HTTP
|
|
25
|
+
|
|
26
|
+
```ts
|
|
27
|
+
import { createGraftMcpHandler } from "@usegraft/mcp";
|
|
28
|
+
|
|
29
|
+
export const POST = createGraftMcpHandler({
|
|
30
|
+
contentDir,
|
|
31
|
+
collections,
|
|
32
|
+
db,
|
|
33
|
+
actor: resolveActor,
|
|
34
|
+
connectionActor: resolveConnectionActor,
|
|
35
|
+
});
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
`connectionActor` is not optional in practice. Without it every write-tool scope check is silently disabled, so pass it whenever a tool can write.
|
|
39
|
+
|
|
40
|
+
## Tools
|
|
41
|
+
|
|
42
|
+
Content: `list_content`, `read_content`, `write_content`, `delete_content`, `search_content`. Introspection: `describe_schema`, `list_functions`, `describe_function`. Execution: `run_function`. Registry: `list_registry`, `describe_item`. Approvals: `list_approvals`, `decide_approval`.
|
|
43
|
+
|
|
44
|
+
## Defaults that fail closed
|
|
45
|
+
|
|
46
|
+
- Anonymous callers are refused unless explicitly allowed.
|
|
47
|
+
- `write_content` requires the `content:write` scope, and being authenticated earns nothing on its own.
|
|
48
|
+
- `delete_content` is destructive and always human-gated: the first call files an approval and fails with its id.
|
|
49
|
+
- Authored MDX is refused if it contains `{…}` expressions, `import`, `export` or spread attributes, because rendering evaluates MDX as JavaScript on the server.
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
MIT. [Repository](https://github.com/AndersonDesign1/graft) · [Changelog](https://github.com/AndersonDesign1/graft/blob/feat/core/packages/mcp/CHANGELOG.md) · [Security policy](https://github.com/AndersonDesign1/graft/blob/feat/core/SECURITY.md)
|
package/dist/index.d.ts
CHANGED
|
@@ -2,8 +2,16 @@ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
|
2
2
|
import { Storage } from '@usegraft/assets';
|
|
3
3
|
import { AnyCollection, AnyGraftFunction, FunctionActor, RateLimit } from '@usegraft/core';
|
|
4
4
|
import { Database, BranchScope, AuditStore, ApprovalStore } from '@usegraft/db';
|
|
5
|
+
import { MdxTrust } from '@usegraft/mdx-safety';
|
|
5
6
|
import { ErrorCode } from '@usegraft/contracts';
|
|
6
7
|
|
|
8
|
+
/**
|
|
9
|
+
* How a Graft MCP server is configured.
|
|
10
|
+
*
|
|
11
|
+
* Split out of server.ts so tool modules can name it without importing the
|
|
12
|
+
* server that hosts them.
|
|
13
|
+
*/
|
|
14
|
+
|
|
7
15
|
interface GraftMcpOptions {
|
|
8
16
|
/** Absolute path to the content root (documents live at <contentDir>/<collection>/<slug>.mdx). */
|
|
9
17
|
contentDir: string;
|
|
@@ -27,6 +35,13 @@ interface GraftMcpOptions {
|
|
|
27
35
|
* projects still work.
|
|
28
36
|
*/
|
|
29
37
|
functions?: Record<string, AnyGraftFunction>;
|
|
38
|
+
/**
|
|
39
|
+
* How much of MDX authored bodies may be, from `mdxTrust` in graft.config.ts.
|
|
40
|
+
* Defaults to "restricted". Applies to the whole tree on every projection,
|
|
41
|
+
* not just to bodies arriving through write_content, because compile re-reads
|
|
42
|
+
* every authored file including the ones that came from git.
|
|
43
|
+
*/
|
|
44
|
+
mdxTrust?: MdxTrust;
|
|
30
45
|
/** Content branch to project into. Defaults to "main". */
|
|
31
46
|
branchId?: string;
|
|
32
47
|
/**
|
|
@@ -46,6 +61,31 @@ interface GraftMcpOptions {
|
|
|
46
61
|
* createFunctionsHandler / createGraftMcpHandler. Defaults to anonymous.
|
|
47
62
|
*/
|
|
48
63
|
actor?: (request: Request) => FunctionActor | Promise<FunctionActor>;
|
|
64
|
+
/**
|
|
65
|
+
* The identity this connection authenticated as, already resolved.
|
|
66
|
+
*
|
|
67
|
+
* `actor` above resolves a *Request*, which tools do not have — they are
|
|
68
|
+
* JSON-RPC calls on an established connection. Tools that need to know who
|
|
69
|
+
* is calling (rather than merely forwarding a credential) read this instead.
|
|
70
|
+
* The HTTP handler sets it from the bearer it already verified; `graft mcp`
|
|
71
|
+
* sets it from the dev-token identity. Absent means anonymous.
|
|
72
|
+
*/
|
|
73
|
+
connectionActor?: FunctionActor;
|
|
74
|
+
/**
|
|
75
|
+
* Directory `put_asset`'s `path` argument may read from, enabling that
|
|
76
|
+
* argument at all.
|
|
77
|
+
*
|
|
78
|
+
* Unset — which is every remote mount — means `put_asset` has no `path`
|
|
79
|
+
* argument: a remote agent sends bytes as base64 or nothing. It used to pass
|
|
80
|
+
* the raw string to readFileSync with no containment whatsoever, upload the
|
|
81
|
+
* result under a key of the caller's choosing, and return a fetchable URL, so
|
|
82
|
+
* `{ path: "/srv/app/.env" }` was a one-call read of DATABASE_URL, dev tokens
|
|
83
|
+
* and S3 credentials on any HTTP-mounted server.
|
|
84
|
+
*
|
|
85
|
+
* `graft mcp` sets it to the project directory: a local agent uploading a
|
|
86
|
+
* hero image from the repo is the case the argument exists for.
|
|
87
|
+
*/
|
|
88
|
+
localUploadRoot?: string;
|
|
49
89
|
/** Forwarded to createFunctionsHandler for run_function. */
|
|
50
90
|
approvalPolicy?: "none" | "human";
|
|
51
91
|
rateLimit?: RateLimit;
|
|
@@ -76,6 +116,7 @@ interface GraftMcpOptions {
|
|
|
76
116
|
*/
|
|
77
117
|
storage?: Storage | (() => Storage | Promise<Storage>);
|
|
78
118
|
}
|
|
119
|
+
|
|
79
120
|
declare function createGraftMcp(options: GraftMcpOptions): McpServer;
|
|
80
121
|
|
|
81
122
|
interface GraftMcpHandlerOptions extends GraftMcpOptions {
|
|
@@ -86,10 +127,19 @@ interface GraftMcpHandlerOptions extends GraftMcpOptions {
|
|
|
86
127
|
*/
|
|
87
128
|
actor?: (request: Request) => FunctionActor | Promise<FunctionActor>;
|
|
88
129
|
/**
|
|
89
|
-
*
|
|
90
|
-
*
|
|
130
|
+
* Serve callers who did not authenticate.
|
|
131
|
+
*
|
|
132
|
+
* Off by default, and deliberately phrased as an opt-*in* to insecurity: this
|
|
133
|
+
* handler is built to be embedded in a Next.js route, a self-host container,
|
|
134
|
+
* Vercel Fluid, or a Worker, and the previous `requireActor` flag defaulted to
|
|
135
|
+
* off — so forgetting it silently published write_content, put_asset,
|
|
136
|
+
* delete_content and decide_approval to anyone who found the URL.
|
|
137
|
+
*
|
|
138
|
+
* Constructing a handler with neither `actor` nor `allowAnonymous: true`
|
|
139
|
+
* throws, so a deployer who forgets gets a startup failure with a fix line
|
|
140
|
+
* rather than an open endpoint.
|
|
91
141
|
*/
|
|
92
|
-
|
|
142
|
+
allowAnonymous?: boolean;
|
|
93
143
|
}
|
|
94
144
|
type GraftMcpHandler = (request: Request) => Promise<Response>;
|
|
95
145
|
declare function createGraftMcpHandler(options: GraftMcpHandlerOptions): GraftMcpHandler;
|