@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 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
- * Reject anonymous callers with 401. Off by default (a dev server on
90
- * localhost); turn it on for anything reachable from outside.
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
- requireActor?: boolean;
142
+ allowAnonymous?: boolean;
93
143
  }
94
144
  type GraftMcpHandler = (request: Request) => Promise<Response>;
95
145
  declare function createGraftMcpHandler(options: GraftMcpHandlerOptions): GraftMcpHandler;