agentwikis-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 (4) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +54 -0
  3. package/index.js +179 -0
  4. package/package.json +16 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Tonbi Studio
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,54 @@
1
+ # agentwikis-mcp
2
+
3
+ MCP server for [Agent Wikis](https://agentwikis.com) — maintained, agent-readable knowledge bases compiled from messy, fast-moving sources. Read-only, no API key, no account.
4
+
5
+ Four tools shaped for an agent's loop:
6
+
7
+ | Tool | What it does |
8
+ |---|---|
9
+ | `list_wikis` | Every wiki + its declared **scope** (covers / not covered / current-as-of) |
10
+ | `open_wiki` | One wiki's metadata + full document map — orient in a single call |
11
+ | `search` | Ranked pages with a calibrated **`confident` flag** — when `false`, fall back to web search |
12
+ | `read_document` | Full page or a single **section**, with a provenance footer |
13
+
14
+ The scope declarations and the `confident` flag exist so your agent knows when *not* to trust the wiki — measured ~94% correct abstention. Details and the full eval: [agentwikis.com/why-wikis](https://www.agentwikis.com/why-wikis).
15
+
16
+ ## Install
17
+
18
+ **Claude Code**
19
+
20
+ ```bash
21
+ claude mcp add agentwikis -- npx -y agentwikis-mcp
22
+ ```
23
+
24
+ **Codex** (`~/.codex/config.toml`)
25
+
26
+ ```toml
27
+ [mcp_servers.agentwikis]
28
+ command = "npx"
29
+ args = ["-y", "agentwikis-mcp"]
30
+ ```
31
+
32
+ **Any MCP client** (JSON config)
33
+
34
+ ```json
35
+ { "mcpServers": { "agentwikis": { "command": "npx", "args": ["-y", "agentwikis-mcp"] } } }
36
+ ```
37
+
38
+ ## Self-hosted instances
39
+
40
+ Point the bridge at your own Agent Wikis deployment (e.g. a private-wiki install):
41
+
42
+ ```bash
43
+ AGENTWIKIS_URL=https://wikis.internal.example npx -y agentwikis-mcp
44
+ ```
45
+
46
+ ## What's inside
47
+
48
+ The bridge talks to `agentwikis.com/api/*` and returns the same payloads as the self-hosted stdio server — same document formatting, same provenance footers, same search calibration. Requires Node 18+.
49
+
50
+ Agent Wikis also serves everything as plain Markdown + [llms.txt](https://www.agentwikis.com/llms.txt) if you'd rather skip MCP entirely: see [agentwikis.com/for-agents](https://www.agentwikis.com/for-agents).
51
+
52
+ ## License
53
+
54
+ MIT
package/index.js ADDED
@@ -0,0 +1,179 @@
1
+ #!/usr/bin/env node
2
+ // agentwikis-mcp — public MCP server for Agent Wikis (https://agentwikis.com).
3
+ // A thin stdio<->HTTP bridge over the site's /api endpoints, so agents get the
4
+ // same payloads (formatting, provenance footers, calibrated `confident` flag)
5
+ // as the self-hosted server. Read-only; no API key required.
6
+ //
7
+ // Point at a different instance with AGENTWIKIS_URL (e.g. a self-hosted app).
8
+
9
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
10
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
11
+ import {
12
+ ListToolsRequestSchema,
13
+ CallToolRequestSchema,
14
+ } from '@modelcontextprotocol/sdk/types.js';
15
+
16
+ const BASE = (process.env.AGENTWIKIS_URL || 'https://agentwikis.com').replace(/\/$/, '');
17
+ const VERSION = '0.1.0';
18
+
19
+ const server = new Server(
20
+ { name: 'agentwikis', version: VERSION },
21
+ { capabilities: { tools: {} } }
22
+ );
23
+
24
+ const TOOLS = [
25
+ {
26
+ name: 'list_wikis',
27
+ description:
28
+ 'List all available wikis with metadata: slug, title, description, ' +
29
+ 'tags, status, last updated, document count, and `scope` (what each wiki ' +
30
+ 'covers, what it does NOT cover, and how current it is — use this to pick a ' +
31
+ 'wiki and to decide when to fall back to web search). Includes "coming soon" ' +
32
+ 'placeholders, marked by status.',
33
+ inputSchema: { type: 'object', properties: {}, additionalProperties: false },
34
+ },
35
+ {
36
+ name: 'open_wiki',
37
+ description:
38
+ 'Orient yourself in one wiki, in a single call: returns its metadata, '
39
+ + '`scope` (coverage / not-covered / freshness), document count, the entry '
40
+ + 'document, and a `map` of all documents (paths + titles, grouped by folder) so '
41
+ + 'you can pick what to read_document next. Use a slug from list_wikis.',
42
+ inputSchema: {
43
+ type: 'object',
44
+ properties: {
45
+ wiki: { type: 'string', description: 'Wiki slug, e.g. "hermes".' },
46
+ },
47
+ required: ['wiki'],
48
+ additionalProperties: false,
49
+ },
50
+ },
51
+ {
52
+ name: 'read_document',
53
+ description:
54
+ 'Read one document in a wiki. Without `section`, returns the full ' +
55
+ 'Markdown (frontmatter stripped) plus a provenance footer. To save tokens on ' +
56
+ 'a long page, pass `section` (a heading title as it appears in the page body, ' +
57
+ 'or its slug anchor) to retrieve ONLY that section and its subsections. ' +
58
+ 'The Markdown may contain [[wikilinks]] to related docs — follow one by ' +
59
+ 'calling read_document with path "wiki/<target>.md".',
60
+ inputSchema: {
61
+ type: 'object',
62
+ properties: {
63
+ wiki: { type: 'string', description: 'Wiki slug, e.g. "llama-cpp".' },
64
+ path: {
65
+ type: 'string',
66
+ description: 'Document path within the wiki, e.g. "wiki/concepts/setup.md".',
67
+ },
68
+ section: {
69
+ type: 'string',
70
+ description:
71
+ 'Optional. A section anchor or heading title to read just that part.',
72
+ },
73
+ },
74
+ required: ['wiki', 'path'],
75
+ additionalProperties: false,
76
+ },
77
+ },
78
+ {
79
+ name: 'search',
80
+ description:
81
+ 'Find the best-matching PAGES for a query, ranked by how many of your query '
82
+ + 'terms each page covers. Searches one wiki if `wiki` is given, otherwise every '
83
+ + 'active wiki. Each result has its wiki, path, matched terms, and a short snippet '
84
+ + 'for orientation — then read_document the page to get the answer. Returns a '
85
+ + '`confident` flag: if false, the wiki(s) likely lack this — fall back to web search.',
86
+ inputSchema: {
87
+ type: 'object',
88
+ properties: {
89
+ query: { type: 'string', description: 'Natural-language or keyword query.' },
90
+ wiki: {
91
+ type: 'string',
92
+ description: 'Optional wiki slug to restrict the search. Omit to search all wikis.',
93
+ },
94
+ },
95
+ required: ['query'],
96
+ additionalProperties: false,
97
+ },
98
+ },
99
+ ];
100
+
101
+ function ok(textOrObj) {
102
+ const text = typeof textOrObj === 'string' ? textOrObj : JSON.stringify(textOrObj);
103
+ return { content: [{ type: 'text', text }] };
104
+ }
105
+
106
+ function fail(message) {
107
+ return { content: [{ type: 'text', text: `Error: ${message}` }], isError: true };
108
+ }
109
+
110
+ // GET a JSON endpoint. On non-200, surfaces the API's own `error` message (plus
111
+ // any hints like available slugs or section anchors) so agents can self-correct.
112
+ async function api(pathname, params = {}) {
113
+ const url = new URL(BASE + pathname);
114
+ for (const [k, v] of Object.entries(params)) {
115
+ if (v !== undefined && v !== null && v !== '') url.searchParams.set(k, String(v));
116
+ }
117
+ const res = await fetch(url, {
118
+ headers: { 'User-Agent': `agentwikis-mcp/${VERSION}` },
119
+ signal: AbortSignal.timeout(30_000),
120
+ });
121
+ let body = null;
122
+ try { body = await res.json(); } catch { /* non-JSON error body */ }
123
+ if (!res.ok) {
124
+ const parts = [body?.error || `HTTP ${res.status} from ${url.pathname}`];
125
+ if (body?.available) parts.push(`Available: ${body.available.join(', ')}.`);
126
+ if (body?.sections) parts.push(`Available sections: ${body.sections.join(', ')}.`);
127
+ throw new Error(parts.join(' '));
128
+ }
129
+ if (body === null) throw new Error(`Unexpected non-JSON response from ${url.pathname}`);
130
+ return body;
131
+ }
132
+
133
+ server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: TOOLS }));
134
+
135
+ server.setRequestHandler(CallToolRequestSchema, async (req) => {
136
+ const { name } = req.params;
137
+ const args = req.params.arguments || {};
138
+ try {
139
+ switch (name) {
140
+ case 'list_wikis':
141
+ return ok(await api('/api/wikis'));
142
+
143
+ case 'open_wiki': {
144
+ if (!args.wiki) return fail('Missing required argument "wiki".');
145
+ return ok(await api(`/api/wiki/${encodeURIComponent(args.wiki)}/open`));
146
+ }
147
+
148
+ case 'read_document': {
149
+ if (!args.wiki || !args.path) return fail('Both "wiki" and "path" are required.');
150
+ const doc = await api(`/api/wiki/${encodeURIComponent(args.wiki)}/doc`, {
151
+ path: args.path,
152
+ section: args.section,
153
+ });
154
+ return ok(doc.text);
155
+ }
156
+
157
+ case 'search': {
158
+ if (!args.query) return fail('Missing required argument "query".');
159
+ return ok(await api('/api/search', { q: args.query, wiki: args.wiki }));
160
+ }
161
+
162
+ default:
163
+ return fail(`Unknown tool "${name}".`);
164
+ }
165
+ } catch (err) {
166
+ return fail(`Tool "${name}" failed: ${err.message}`);
167
+ }
168
+ });
169
+
170
+ async function main() {
171
+ const transport = new StdioServerTransport();
172
+ await server.connect(transport);
173
+ console.error(`Agent Wikis MCP bridge running on stdio (${BASE}).`);
174
+ }
175
+
176
+ main().catch((err) => {
177
+ console.error('Fatal MCP server error:', err);
178
+ process.exit(1);
179
+ });
package/package.json ADDED
@@ -0,0 +1,16 @@
1
+ {
2
+ "name": "agentwikis-mcp",
3
+ "version": "0.1.0",
4
+ "description": "MCP server for Agent Wikis (agentwikis.com) — maintained, agent-readable knowledge bases with calibrated search and provenance. Read-only, no API key.",
5
+ "type": "module",
6
+ "bin": { "agentwikis-mcp": "./index.js" },
7
+ "main": "index.js",
8
+ "engines": { "node": ">=18" },
9
+ "license": "MIT",
10
+ "repository": { "type": "git", "url": "git+https://github.com/tonbistudio/agentwikis-mcp.git" },
11
+ "homepage": "https://agentwikis.com/for-agents",
12
+ "keywords": ["mcp", "model-context-protocol", "knowledge-base", "llms-txt", "agents", "documentation"],
13
+ "dependencies": {
14
+ "@modelcontextprotocol/sdk": "^1.0.0"
15
+ }
16
+ }