@littlebigbrain/mcp 0.5.1 → 0.6.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 CHANGED
@@ -1,38 +1,52 @@
1
1
  # @littlebigbrain/mcp
2
2
 
3
- Eight task-shaped [MCP](https://modelcontextprotocol.io) tools that let Claude, Cursor, Codex, or any MCP client search, query, and write a [Little Big Brain](https://littlebigbrain.com) graph. Ships two ways: a hosted endpoint with OAuth sign-in, and a local stdio server.
3
+ [Model Context Protocol (MCP)](https://modelcontextprotocol.io) server for
4
+ [little big brain](https://littlebigbrain.com), a search platform for AI
5
+ applications such as chatbots, search tools, and agents.
4
6
 
5
- ## Hosted (OAuth) — recommended
7
+ Connect an MCP client to search your data, follow relationships, and read the
8
+ facts behind an answer. The tools also let you load data and define validation
9
+ rules.
6
10
 
7
- The client opens WorkOS sign-in; your machine never stores a Little Big Brain key. Point it at your stack:
11
+ [Documentation](https://docs.littlebigbrain.com/sdks/mcp/) ·
12
+ [Quickstart](https://docs.littlebigbrain.com/start/quickstart/) ·
13
+ [Issues](https://github.com/littlebigbrains/lbb-mcp/issues)
8
14
 
9
- ```json
10
- {
11
- "mcpServers": {
12
- "lbb": {
13
- "url": "https://mcp.littlebigbrain.com/mcp/<stack-slug>"
14
- }
15
- }
16
- }
15
+ ## Connect
16
+
17
+ Create a stack in the [console](https://cloud.littlebigbrain.com), then choose a
18
+ hosted connection or a local process.
19
+
20
+ ### Hosted connection
21
+
22
+ For clients that support remote MCP with OAuth, use this URL and sign in with
23
+ your little big brain account. Replace `<stack-slug>` with your stack's slug:
24
+
25
+ ```text
26
+ https://mcp.littlebigbrain.com/mcp/<stack-slug>
17
27
  ```
18
28
 
19
- Codex sends the URL as an OAuth `resource`, so use the origin plus a stack header instead:
29
+ For clients that use an `mcpServers` JSON configuration:
20
30
 
21
31
  ```json
22
32
  {
23
33
  "mcpServers": {
24
34
  "lbb": {
25
- "type": "http",
26
- "url": "https://mcp.littlebigbrain.com",
27
- "headers": { "X-LBB-Stack": "<stack-slug>" }
35
+ "url": "https://mcp.littlebigbrain.com/mcp/<stack-slug>"
28
36
  }
29
37
  }
30
38
  }
31
39
  ```
32
40
 
33
- ## Local (stdio)
41
+ This connection uses account sign-in and does not require a stack API key.
42
+ The [connection guide](https://docs.littlebigbrain.com/sdks/mcp/#hosted-streamable-http-oauth)
43
+ includes client-specific setup, including the origin URL and `X-LBB-Stack` header
44
+ for Codex.
45
+
46
+ ### Local process
34
47
 
35
- Run against any data-plane endpoint with a stack API key:
48
+ Requires Node.js 18+. Copy the complete endpoint and a stack API key from
49
+ **Connect** in the console, then add them to your client's MCP configuration:
36
50
 
37
51
  ```json
38
52
  {
@@ -41,147 +55,126 @@ Run against any data-plane endpoint with a stack API key:
41
55
  "command": "npx",
42
56
  "args": ["-y", "@littlebigbrain/mcp"],
43
57
  "env": {
44
- "LBB_BASE_URL": "https://0abc1def--production.db.eu.littlebigbrain.com",
45
- "LBB_API_KEY": "lbb_sk_live_..."
58
+ "LBB_BASE_URL": "https://<your-complete-stack-host>",
59
+ "LBB_API_KEY": "<your-stack-api-key>"
46
60
  }
47
61
  }
48
62
  }
49
63
  }
50
64
  ```
51
65
 
52
- Set `LBB_GRAPH` or `LBB_BRANCH` to target a scope other than `main`.
53
- `LBB_BASE_URL` has no hosted default: copy `endpoint_url` from the stack's
54
- Connect page. The MCP process exits with a configuration error when it is
55
- missing.
66
+ The client starts the server and communicates through standard input and output
67
+ (stdio). Keep the key in your local configuration. Set `LBB_GRAPH` to change
68
+ the default graph from `main`.
56
69
 
57
- ## Tools
70
+ ## Run a first query
58
71
 
59
- | Tool | Use it for |
60
- | --- | --- |
61
- | `lbb_inspect` | graph discovery, complete paginated ontology/schema, publication status, entity, state, history, and provenance |
62
- | `lbb_rdf` | import full RDF/OWL or add axioms using INSERT DATA |
63
- | `lbb_query` | SPARQL text, structured SPARQL bodies, and canned analysis |
64
- | `lbb_commit` | facts, properties, and embeddings |
65
- | `lbb_observe` | conversation episodes plus reviewed extraction |
66
- | `lbb_branch` | isolation branches and validated merge |
67
- | `lbb_models` | shadow evaluation and training datasets |
68
- | `lbb_configure` | native ontology definition/evolution and SHACL preview/publication |
69
-
70
- Read tools return compact structured envelopes by default — use `detail`, `row_limit`, and returned cursors to page without silently truncating. Write tools derive an idempotency key unless you provide one.
71
-
72
- Query pages preserve complete RDF values and may contain fewer than `row_limit`
73
- rows to fit the 80 KB UTF-8 output budget. Follow the returned `next` arguments
74
- until absent; the cursor advances by rows actually delivered. A single row that
75
- exceeds the budget fails explicitly: project fewer fields or use the direct
76
- SPARQL HTTP endpoint for that row.
77
-
78
-
79
- Both `lbb_query` SPARQL modes (`sparql` and `structured`) support retained commit reads
80
- through `as_of_commit_seq`. When omitted, the connector pins the current head
81
- commit and reuses it for cursor pages. Valid-time `as_of` is unsupported and is
82
- rejected before an API call, including when carried in an old cursor. Start a
83
- new query without that selector or choose a retained commit sequence.
84
-
85
- ## Create and evolve an ontology through MCP
86
-
87
- Start with `lbb_inspect action=guide`; `action=graphs` helps select an existing
88
- scope, and a missing graph returns bootstrap guidance. Decide what questions
89
- the graph must answer before choosing classes and relations. Distinguish
90
- source-backed facts from hypotheses, and preserve evidence and dates.
91
-
92
- Native metadata and stored RDF axioms are separate:
93
-
94
- - `lbb_configure action=define_ontology` accepts a friendly `spec`, including
95
- class `super_types`. Unknown spec fields fail explicitly. `lbb_json` expects
96
- an internal serialized ontology, not a friendly spec. Raw OWL supplied to
97
- configure is reduced to native metadata; it is not stored as a full document.
98
- - `lbb_rdf action=import` stores the complete Turtle, N-Triples, N-Quads, or TriG
99
- document as queryable graph facts, including RDF lists, annotations, and OWL
100
- axioms. Pass `source`; the published RDF tier supports only the default RDF
101
- graph. Dataset formats must contain only default-graph quads. The first RDF
102
- data write selects RDF-native storage, which refuses
103
- later property-graph commits; choose the write workflow before bootstrap.
104
- - `lbb_configure action=evolve_ontology` supports explicit native changes,
105
- including `add_super_types`. `dry_run: true` previews define/evolve/publish;
106
- the same flag previews `lbb_commit mode=facts` without writing.
107
- - `lbb_rdf action=update` submits SPARQL Update unchanged; currently only
108
- `INSERT DATA` is supported. DELETE, WHERE, and graph replacement are refused.
109
- Re-importing is
110
- additive and does not remove obsolete axioms. Content-based retry keys are
111
- automatic; use a new explicit key for an intentional repeat after other edits.
112
-
113
- For example, add a superclass without a browser or RDF conversion:
72
+ This example stores three facts in a graph named `quickstart`: a service writes
73
+ to a database, and each has a label. The graph is created on its first write.
74
+
75
+ Ask your client to call `lbb_rdf` with these arguments:
114
76
 
115
77
  ```json
116
78
  {
117
- "action": "update",
118
- "update": "INSERT DATA { <urn:Person> <http://www.w3.org/2000/01/rdf-schema#subClassOf> <urn:Contact> }"
79
+ "action": "import",
80
+ "graph": "quickstart",
81
+ "format": "ntriples",
82
+ "source": "<https://example.org/auth-service> <https://example.org/writesTo> <https://example.org/user-db> .\n<https://example.org/auth-service> <http://www.w3.org/2000/01/rdf-schema#label> \"Auth Service\" .\n<https://example.org/user-db> <http://www.w3.org/2000/01/rdf-schema#label> \"User Database\" .",
83
+ "idempotency_key": "mcp-quickstart-v1"
119
84
  }
120
85
  ```
121
86
 
122
- Removing or replacing RDF axioms requires native bounded update support in the
123
- engine. Until then, import a revised document into a new versioned LBB graph,
124
- verify it, and explicitly switch consumers. Do not implicitly delete the original.
125
-
126
- `publish_schema` activates SHACL shapes against unchanged native metadata.
127
- Its preview checks parsing and compatibility without writing objects or
128
- scheduling jobs; it does not audit the entire graph. Preview restrictive
129
- native edits with evolve, resolve conflicts, then apply. For restrictive
130
- SHACL, use warn → inspect conformance → repair → reject.
131
-
132
- After applying, inspect `action=publication`, then verify both asserted axioms
133
- and expected inferred answers. `lbb_query mode=sparql` accepts explicit
134
- `entailment: "none" | "subclass" | "rdfs" | "owl"` (default `none`),
135
- `consistency: "eventual" | "strong"`, and `min_indexed_seq`. Cursors retain
136
- these controls. OWL is the server's supported inference profile, not arbitrary
137
- OWL DL. An upload acknowledgement is not proof of successful reasoning.
138
-
139
- To read asserted axioms in the default graph, query with `entailment: "none"`
140
- and follow all returned row cursors:
141
-
142
- ```sparql
143
- SELECT ?s ?p ?o WHERE {
144
- ?s ?p ?o
145
- } ORDER BY ?s ?p ?o
87
+ Now ask **which database does Auth Service write to?** The `lbb_query` call is:
88
+
89
+ ```json
90
+ {
91
+ "mode": "sparql",
92
+ "graph": "quickstart",
93
+ "consistency": "strong",
94
+ "query": "SELECT ?database WHERE { <https://example.org/auth-service> <https://example.org/writesTo> ?db . ?db <http://www.w3.org/2000/01/rdf-schema#label> ?database } ORDER BY ?database LIMIT 10"
95
+ }
146
96
  ```
147
97
 
148
- `lbb_inspect action=ontology` and `action=schema` page complete native metadata
149
- with `page_size` (default 50, maximum 500), optional `section`, and `cursor`.
150
- Pass the returned `next` arguments until absent. These pages preserve nested
151
- values even with `detail=compact`; they never replace the remainder with a
152
- suggestion to repeat `detail=full`. If a single entry is too large, the result
153
- contains `entry_fragment`: concatenate `serialized_json` by `char_offset`, then
154
- JSON-parse the completed entry. Changed metadata invalidates the cursor rather
155
- than mixing versions. Restart inspection after applying edits.
98
+ The result contains one row on a fresh graph:
99
+
100
+ | database |
101
+ | --- |
102
+ | User Database |
103
+
104
+ The query follows a stored relationship to its database label. Strong consistency
105
+ lets it read the import without waiting for a background index job.
106
+
107
+ For your own data, start with `lbb_inspect` using `action: "guide"` or
108
+ `action: "ontology"`. Imported Resource Description Framework (RDF) data keeps
109
+ its original identifiers; inspect it with SPARQL when choosing query predicates.
110
+
111
+ ## Tools
112
+
113
+ | Tool | Purpose |
114
+ | --- | --- |
115
+ | `lbb_inspect` | Read the schema, graph status, entities, history, and evidence. |
116
+ | `lbb_query` | Run SPARQL queries, search by meaning, or request summary statistics. |
117
+ | `lbb_rdf` | Import RDF documents or add facts with SPARQL `INSERT DATA`. |
118
+ | `lbb_embeddings` | Inspect search setup and preview the text to embed. |
119
+ | `lbb_embeddings_manage` | Set up or refresh embeddings, or change the embedding model. |
120
+ | `lbb_embeddings_delete` | Delete an embedding and its stored vectors. |
121
+ | `lbb_commit` | Write or retract JSON facts, or record search feedback. |
122
+ | `lbb_configure` | Define record types and relationships, or publish validation rules. |
123
+ | `lbb_evals` | Label query results and check whether later queries return the expected answers. |
124
+ | `lbb_models` | Compare retrieval settings and read model training datasets. |
125
+
126
+ See [search by meaning](https://docs.littlebigbrain.com/guides/search-by-meaning/)
127
+ for embedding setup. To define constraints with the Shapes Constraint Language
128
+ (SHACL), see [query and validation](https://docs.littlebigbrain.com/guides/sparql-and-shacl/).
129
+
130
+ RDF imports and JSON facts use different write workflows. A graph first written
131
+ through `lbb_rdf` does not accept JSON fact writes through `lbb_commit`. Choose
132
+ the workflow when creating the graph. RDF updates
133
+ support additive `INSERT DATA`;
134
+ see the [RDF guide](https://docs.littlebigbrain.com/guides/load-rdf/) for format and
135
+ update limits.
136
+
137
+ ## Pages and saved queries
138
+
139
+ When a result includes `next`, pass those arguments to the same tool to read the
140
+ next page. Continue until `next` is absent. `row_limit` sets a maximum; large
141
+ values can make a page shorter.
142
+
143
+ SPARQL queries keep the same commit across pages. Save the query and its returned
144
+ commit sequence to check an answer later, then use `as_of_commit_seq` to select
145
+ that version. See [history and replay](https://docs.littlebigbrain.com/guides/time-travel-audit/)
146
+ for retention and evidence handling.
156
147
 
157
148
  ## Embed the server
158
149
 
159
- For self-hosting behind your own auth, the package also serves the tools over HTTP:
150
+ To serve the tools from your own Node.js process:
160
151
 
161
152
  ```ts
162
153
  import { createMcpHttpServer } from "@littlebigbrain/mcp";
163
154
 
164
155
  createMcpHttpServer({
165
- baseUrl: "https://0abc1def--production.db.eu.littlebigbrain.com",
156
+ baseUrl: process.env.LBB_BASE_URL!,
166
157
  mcpPath: "/mcp",
167
158
  allowedHosts: ["127.0.0.1", "localhost", "::1"],
168
159
  }).listen(8080, "127.0.0.1");
169
160
  ```
170
161
 
171
- The embedded server passes a key bearer to the data plane; the hosted endpoint's OAuth and ownership layer is served separately by the Little Big Brain API.
172
-
173
- Full tool schemas and examples: [docs.littlebigbrain.com/sdks/mcp](https://docs.littlebigbrain.com/sdks/mcp/).
162
+ Clients connect to `http://127.0.0.1:8080/mcp` and send a stack API key in
163
+ `Authorization: Bearer <key>`. See the
164
+ [Node.js integration guide](https://docs.littlebigbrain.com/sdks/mcp/#embed-in-a-node-process)
165
+ for HTTP options and integration with an existing MCP server.
174
166
 
175
- ## Local end-to-end ontology check
167
+ ## Development
176
168
 
177
- From the repository root, build the server and SDKs, then opt into the isolated
178
- real-server MCP test (it creates and removes its own temporary data root):
169
+ From a clone of this repository:
179
170
 
180
171
  ```sh
181
- cargo build -p lbb-server
182
- npm run build -w @littlebigbrain/client
183
- LBB_TEST_SERVER_BIN="$PWD/target/debug/lbb-server" npm test -w @littlebigbrain/mcp
172
+ npm ci
173
+ npm run build
174
+ npm run typecheck
175
+ npm test
184
176
  ```
185
177
 
186
- The test verifies native hierarchy evolution, preservation of RDF annotations,
187
- subclass/inverse inference, additive edits, and refusal of unsupported deletion.
178
+ ## License
179
+
180
+ [Apache-2.0](LICENSE).
@@ -22,7 +22,6 @@ export interface McpHttpServerOptions {
22
22
  baseUrl: string;
23
23
  apiKey: string;
24
24
  graph?: string;
25
- branch?: string;
26
25
  }) => LbbClient;
27
26
  }
28
27
  export declare function bearer(req: IncomingMessage): string | undefined;
@@ -150,7 +150,6 @@ export function createMcpHttpServer(options) {
150
150
  baseUrl,
151
151
  apiKey,
152
152
  graph: url.searchParams.get("graph") ?? undefined,
153
- branch: url.searchParams.get("branch") ?? undefined,
154
153
  };
155
154
  const client = options.clientFactory
156
155
  ? options.clientFactory(clientOptions)
package/dist/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
1
  export { registerLbbTools } from "./tools.js";
2
2
  export { buildLbbServer } from "./server.js";
3
+ export type { LbbServerOptions, McpQueryStage, McpQueryStageEvent, } from "./query-observer.js";
3
4
  export { createMcpHttpServer, type McpHttpServerOptions, } from "./http-server.js";
@@ -4,7 +4,6 @@ import { metadataPageSchema } from "./tool-contracts.js";
4
4
  type Request = z.infer<z.ZodObject<typeof metadataPageSchema>> & {
5
5
  action: "ontology" | "schema";
6
6
  graph?: string;
7
- branch?: string;
8
7
  };
9
8
  /** Stateless pagination of complete entries, including their full nested values.
10
9
  * A digest rejects mixed-version reads instead of skipping/repeating definitions
@@ -24,7 +23,6 @@ export declare function metadataPage(client: LbbClient, args: Request): Promise<
24
23
  next: {
25
24
  action: "ontology" | "schema";
26
25
  graph: string | undefined;
27
- branch: string | undefined;
28
26
  section: string | undefined;
29
27
  page_size: number;
30
28
  cursor: string;
@@ -7,7 +7,6 @@ const cursorSchema = z
7
7
  v: z.literal(1),
8
8
  action: z.enum(["ontology", "schema"]),
9
9
  graph: z.string().optional(),
10
- branch: z.string().optional(),
11
10
  section: z.string().optional(),
12
11
  page_size: z.number().int().min(1).max(500),
13
12
  offset: z.number().int().nonnegative().safe(),
@@ -27,23 +26,16 @@ export async function metadataPage(client, args) {
27
26
  catch {
28
27
  throw new Error("invalid lbb_inspect cursor; restart without cursor");
29
28
  }
30
- for (const key of [
31
- "action",
32
- "graph",
33
- "branch",
34
- "section",
35
- "page_size",
36
- ]) {
29
+ for (const key of ["action", "graph", "section", "page_size"]) {
37
30
  if (args[key] !== undefined && args[key] !== cursor[key]) {
38
31
  throw new Error(`cursor ${key} does not match the supplied ${key}`);
39
32
  }
40
33
  }
41
34
  }
42
35
  const graph = cursor?.graph ?? args.graph;
43
- const branch = cursor?.branch ?? args.branch;
44
36
  const section = cursor?.section ?? args.section;
45
37
  const pageSize = cursor?.page_size ?? args.page_size ?? 50;
46
- const target = client.withScope({ graph, branch });
38
+ const target = client.withScope({ graph });
47
39
  const value = (args.action === "ontology"
48
40
  ? await target.ontologyView({ counts: true })
49
41
  : await target.schema.view());
@@ -62,7 +54,6 @@ export async function metadataPage(client, args) {
62
54
  v: 1,
63
55
  action: args.action,
64
56
  graph,
65
- branch,
66
57
  section,
67
58
  page_size: pageSize,
68
59
  fingerprint,
@@ -94,7 +85,6 @@ export async function metadataPage(client, args) {
94
85
  ? {
95
86
  action: args.action,
96
87
  graph,
97
- branch,
98
88
  section,
99
89
  page_size: pageSize,
100
90
  cursor: Buffer.from(JSON.stringify({
@@ -0,0 +1,33 @@
1
+ /** Local opt-in query measurements. No event contains query or response data. */
2
+ export type McpQueryStage = "query_pin_metadata" | "query_http_total" | "query_results_parse" | "query_envelope" | "query_render";
3
+ export interface McpQueryStageEvent {
4
+ stage: McpQueryStage;
5
+ durationMs: number;
6
+ outcome: "success" | "error";
7
+ mode: "sparql" | "structured";
8
+ continuation: boolean;
9
+ row_limit: number;
10
+ offset: number;
11
+ received_rows?: number;
12
+ returned_rows?: number;
13
+ cursor_bytes?: number;
14
+ text_bytes?: number;
15
+ }
16
+ export interface LbbServerOptions {
17
+ /** Query text only; fitting and rendering always use this same format. */
18
+ queryTextFormat?: "compact" | "pretty";
19
+ timing?: {
20
+ /** Monotonic milliseconds; defaults to performance.now(). */
21
+ now?: () => number;
22
+ observe: (event: Readonly<McpQueryStageEvent>) => void;
23
+ };
24
+ }
25
+ type QueryCounts = Pick<McpQueryStageEvent, "received_rows" | "returned_rows" | "cursor_bytes" | "text_bytes">;
26
+ type QueryIdentity = Pick<McpQueryStageEvent, "mode" | "continuation" | "row_limit" | "offset">;
27
+ /** Each tool call owns its small counter record; servers may serve concurrently. */
28
+ export declare function queryTiming(options: LbbServerOptions, identity: QueryIdentity): {
29
+ counts(update: QueryCounts): void;
30
+ measure<T>(stage: McpQueryStage, operation: () => T): T;
31
+ measureAsync<T>(stage: McpQueryStage, operation: () => Promise<T>): Promise<T>;
32
+ };
33
+ export {};
@@ -0,0 +1,95 @@
1
+ function count(value) {
2
+ return Number.isFinite(value)
3
+ ? Math.min(Number.MAX_SAFE_INTEGER, Math.max(0, Math.floor(value)))
4
+ : 0;
5
+ }
6
+ /** Each tool call owns its small counter record; servers may serve concurrently. */
7
+ export function queryTiming(options, identity) {
8
+ const timing = options.timing;
9
+ const counts = {};
10
+ const now = () => {
11
+ try {
12
+ const value = timing?.now?.() ?? performance.now();
13
+ return Number.isFinite(value) ? value : performance.now();
14
+ }
15
+ catch {
16
+ return performance.now();
17
+ }
18
+ };
19
+ const emit = (stage, start, outcome) => {
20
+ if (!timing)
21
+ return;
22
+ const elapsed = now() - start;
23
+ const event = {
24
+ stage,
25
+ durationMs: Number.isFinite(elapsed)
26
+ ? Math.min(Number.MAX_SAFE_INTEGER, Math.max(0, elapsed))
27
+ : 0,
28
+ outcome,
29
+ mode: identity.mode,
30
+ continuation: identity.continuation,
31
+ row_limit: count(identity.row_limit),
32
+ offset: count(identity.offset),
33
+ ...counts,
34
+ };
35
+ try {
36
+ // Async callbacks also remain isolated even though observation is not
37
+ // awaited and the public callback contract does not require a Promise.
38
+ const pending = timing.observe(event);
39
+ if (pending &&
40
+ typeof pending.then === "function") {
41
+ void Promise.resolve(pending).catch(() => { });
42
+ }
43
+ }
44
+ catch {
45
+ // A local observer cannot turn a successful query into a failure.
46
+ }
47
+ };
48
+ return {
49
+ counts(update) {
50
+ if (!timing)
51
+ return;
52
+ // Explicit keys prevent caller-supplied objects from adding fields.
53
+ for (const key of [
54
+ "received_rows",
55
+ "returned_rows",
56
+ "cursor_bytes",
57
+ "text_bytes",
58
+ ]) {
59
+ const value = update[key];
60
+ if (value !== undefined)
61
+ counts[key] = count(value);
62
+ }
63
+ },
64
+ measure(stage, operation) {
65
+ if (!timing)
66
+ return operation();
67
+ const start = now();
68
+ let outcome = "error";
69
+ try {
70
+ const result = operation();
71
+ outcome = "success";
72
+ return result;
73
+ }
74
+ finally {
75
+ emit(stage, start, outcome);
76
+ }
77
+ },
78
+ measureAsync(stage, operation) {
79
+ if (!timing)
80
+ return operation();
81
+ const start = now();
82
+ return (async () => {
83
+ let outcome = "error";
84
+ try {
85
+ const result = await operation();
86
+ outcome = "success";
87
+ return result;
88
+ }
89
+ finally {
90
+ emit(stage, start, outcome);
91
+ }
92
+ })();
93
+ },
94
+ };
95
+ }
package/dist/rdf-tool.js CHANGED
@@ -49,13 +49,12 @@ export function registerRdfTool(server, client) {
49
49
  return errorResult(parsed.error);
50
50
  const args = parsed.data;
51
51
  return run(client, `lbb_rdf.${args.action}`, args.detail, async () => {
52
- const target = scoped(client, args.graph, args.branch);
52
+ const target = scoped(client, args.graph);
53
53
  const { idempotency_key } = args;
54
54
  const operation = { ...args };
55
55
  delete operation.detail;
56
56
  delete operation.idempotency_key;
57
- const key = idempotency_key ??
58
- contentHashKey({ graph: args.graph, branch: args.branch }, operation);
57
+ const key = idempotency_key ?? contentHashKey({ graph: args.graph }, operation);
59
58
  if (args.action === "import") {
60
59
  return target.importRdf(args.source, {
61
60
  format: args.format ?? "turtle",
package/dist/server.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
2
  import type { LbbClient } from "@littlebigbrain/client";
3
+ import type { LbbServerOptions } from "./query-observer.js";
3
4
  /** Build an MCP server exposing the little big brain tool belt, bound to one client. */
4
- export declare function buildLbbServer(client: LbbClient): McpServer;
5
+ export declare function buildLbbServer(client: LbbClient, options?: LbbServerOptions): McpServer;
package/dist/server.js CHANGED
@@ -3,8 +3,8 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
3
3
  import { registerLbbTools } from "./tools.js";
4
4
  const { version } = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf8"));
5
5
  /** Build an MCP server exposing the little big brain tool belt, bound to one client. */
6
- export function buildLbbServer(client) {
6
+ export function buildLbbServer(client, options = {}) {
7
7
  const server = new McpServer({ name: "lbb", version });
8
- registerLbbTools(server, client);
8
+ registerLbbTools(server, client, options);
9
9
  return server;
10
10
  }
package/dist/stdio.js CHANGED
@@ -12,7 +12,7 @@ const BASE_URL_HELP = "LBB_BASE_URL is required. Copy endpoint_url from your Lit
12
12
  *
13
13
  * LBB_BASE_URL (required for tool calls; copy endpoint_url from the stack Connect page)
14
14
  * LBB_API_KEY stack API key (lbb_sk_live_…) or single-mode token
15
- * LBB_GRAPH / LBB_BRANCH (optional; server defaults to main/main)
15
+ * LBB_GRAPH (optional; server defaults to main)
16
16
  *
17
17
  * The base URL is required lazily, at the first tool invocation, not at
18
18
  * process start: MCP hosts launch servers to complete the initialize
@@ -44,7 +44,6 @@ async function main() {
44
44
  baseUrl,
45
45
  apiKey: process.env.LBB_API_KEY,
46
46
  graph: process.env.LBB_GRAPH,
47
- branch: process.env.LBB_BRANCH,
48
47
  })
49
48
  : unconfiguredClient();
50
49
  const server = buildLbbServer(client);