@imqueue/mcp 1.0.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/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ @imqueue/mcp — Model Context Protocol server for @imqueue
2
+ Copyright (C) 2026 imqueue.com
3
+
4
+ This program is free software: you can redistribute it and/or modify it under
5
+ the terms of the GNU General Public License as published by the Free Software
6
+ Foundation, either version 3 of the License, or (at your option) any later
7
+ version.
8
+
9
+ This program is distributed in the hope that it will be useful, but WITHOUT ANY
10
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
11
+ PARTICULAR PURPOSE. See the GNU General Public License for more details.
12
+
13
+ You should have received a copy of the GNU General Public License along with
14
+ this program. If not, see <https://www.gnu.org/licenses/gpl-3.0.html>.
15
+
16
+ Commercial licensing and support for use in closed-source products is available
17
+ at https://imqueue.com.
18
+
19
+ NOTE: replace this notice with the full GPL-3.0 license text before publishing
20
+ (https://www.gnu.org/licenses/gpl-3.0.txt).
package/README.md ADDED
@@ -0,0 +1,65 @@
1
+ # @imqueue/mcp
2
+
3
+ A [Model Context Protocol](https://modelcontextprotocol.io) server for **[@imqueue](https://imqueue.org)**. It lets AI coding agents (Claude Code, Cursor, Windsurf, VS Code, …) **search the @imqueue documentation** and **scaffold typed services & clients** — so they generate correct, idiomatic @imqueue code instead of guessing.
4
+
5
+ ## Tools
6
+
7
+ | Tool | What it does |
8
+ |---|---|
9
+ | `search_docs` | Search the official docs (guides, tutorial, CLI manual, API reference, articles) and return the most relevant pages + URLs. |
10
+ | `get_doc` | Fetch the full markdown of a doc page by URL. |
11
+ | `list_packages` | List the main @imqueue packages with install commands. |
12
+ | `scaffold_service` | Generate an `IMQService` subclass with `@expose()`d, JSDoc-typed methods + a bootstrap. |
13
+ | `scaffold_client` | Show how to generate and use the fully-typed client for a service. |
14
+
15
+ Docs are fetched live from imqueue.org's machine-readable feeds (`/llms.txt`, per-page `…/index.md` mirrors), so the server never ships stale content. It only ever fetches `imqueue.org`.
16
+
17
+ ## Install
18
+
19
+ Requires Node.js ≥ 18. No build step for users — run straight from npm:
20
+
21
+ ```bash
22
+ npx -y @imqueue/mcp
23
+ ```
24
+
25
+ ### Claude Code
26
+
27
+ ```bash
28
+ claude mcp add imqueue -- npx -y @imqueue/mcp
29
+ ```
30
+
31
+ ### Cursor / Windsurf / VS Code / Claude Desktop
32
+
33
+ Add to your MCP config (`.cursor/mcp.json`, `claude_desktop_config.json`, …):
34
+
35
+ ```json
36
+ {
37
+ "mcpServers": {
38
+ "imqueue": {
39
+ "command": "npx",
40
+ "args": ["-y", "@imqueue/mcp"]
41
+ }
42
+ }
43
+ }
44
+ ```
45
+
46
+ ## Develop
47
+
48
+ ```bash
49
+ npm install
50
+ npm run build # tsc -> dist/
51
+ npm run dev # run from source with tsx
52
+ npm run smoke # JSON-RPC handshake + tools/list + tool calls
53
+ ```
54
+
55
+ ## Example
56
+
57
+ > **User:** *"Create an @imqueue user service with a getUser(id) method."*
58
+ >
59
+ > The agent calls `scaffold_service({ name: "user", methods: [{ name: "getUser", params: [{ name: "id", type: "number" }], returns: "User" }] })` and gets a ready-to-paste `UserService` + bootstrap, then `search_docs("run a service")` / `get_doc(...)` to wire it up.
60
+
61
+ ## License
62
+
63
+ GPL-3.0. Commercial licensing & support for closed-source products: [imqueue.com](https://imqueue.com).
64
+
65
+ See [SPEC.md](./SPEC.md) for the full design and registry-distribution plan.
package/SPEC.md ADDED
@@ -0,0 +1,119 @@
1
+ # @imqueue/mcp — design spec
2
+
3
+ ## 1. Purpose
4
+
5
+ Make @imqueue **first-class inside AI coding agents**. When a developer asks their
6
+ assistant to "build an @imqueue service" or "how do I expose a method", the agent
7
+ should reach for authoritative docs and correct scaffolding rather than
8
+ hallucinating an API. This is the GEO (Generative Engine Optimization) counterpart
9
+ to SEO: instead of ranking in a search page, we rank **at code-time**, inside the
10
+ tools developers already use.
11
+
12
+ Two capabilities, five tools:
13
+
14
+ - **Docs access** — `search_docs`, `get_doc`, `list_packages`
15
+ - **Scaffolding** — `scaffold_service`, `scaffold_client`
16
+
17
+ ## 2. Architecture
18
+
19
+ ```
20
+ AI agent (Claude Code / Cursor / …)
21
+ │ MCP (JSON-RPC over stdio)
22
+
23
+ @imqueue/mcp ── fetch ──▶ imqueue.org
24
+ ├─ docs.ts (/llms.txt, /<page>/index.md)
25
+ ├─ packages.ts (static catalog)
26
+ └─ scaffold.ts (code templates)
27
+ ```
28
+
29
+ - **Transport:** stdio (the universal local-MCP transport; works with every host
30
+ today). A hosted **Streamable HTTP** variant is a later option (§7).
31
+ - **Runtime:** Node ≥ 18, TypeScript, `@modelcontextprotocol/sdk` high-level
32
+ `McpServer`, `zod` input schemas. Ships as an npm bin (`npx -y @imqueue/mcp`).
33
+ - **Docs source:** fetched live from imqueue.org's existing machine-readable feeds
34
+ and cached in-process (1 h TTL). No docs are bundled, so the server can never go
35
+ stale against a release. **Only `imqueue.org` is ever fetched** (host-checked).
36
+
37
+ ### Why reuse the site feeds
38
+ imqueue.org already emits, for GEO:
39
+ - `/llms.txt` — curated index (`## Section` + `- [Title](url): description`)
40
+ - `/<page-url>index.md` — a plain-markdown mirror of every page
41
+ - `/blog/search-index.json` — structured post index
42
+
43
+ The MCP server is a thin, agent-facing adapter over those — one source of truth.
44
+
45
+ ## 3. Tools
46
+
47
+ ### `search_docs(query, limit?=6)`
48
+ Parse `/llms.txt` into `{title, url, description, section}` entries; rank by query-term
49
+ overlap (title ×3, section/description/url ×1); return the top *N* with URLs.
50
+ → *"how do I expose a method" → the RPC guide + API pages.*
51
+
52
+ ### `get_doc(url)`
53
+ Resolve a page URL to its markdown mirror (`…/index.md`) and return the raw markdown
54
+ for reading/quoting. Host-restricted to imqueue.org.
55
+
56
+ ### `list_packages()`
57
+ Static catalog (rpc, core, cli, job, pg-pubsub, pg-cache, async-logger, http-protect)
58
+ with one-liners + install commands, so the agent picks the right package first.
59
+
60
+ ### `scaffold_service(name, methods?)`
61
+ Emit an `IMQService` subclass with `@expose()`d, **JSDoc-typed** methods (JSDoc is
62
+ @imqueue's type source) + a bootstrap that `start()`s it. Omitting `methods` yields a
63
+ starter template. Points to `imq service create` for a fully provider-wired project.
64
+
65
+ ### `scaffold_client(service, methods?)`
66
+ @imqueue generates the **real** typed client from a **running** service
67
+ (`imq client generate <Name>`), so types never drift. The tool returns that command
68
+ plus an illustrative usage snippet (it does not fabricate a client that could go stale).
69
+
70
+ ## 4. Input schemas (zod)
71
+
72
+ - `search_docs`: `{ query: string, limit?: 1..20 }`
73
+ - `get_doc`: `{ url: string }`
74
+ - `list_packages`: `{}`
75
+ - `scaffold_service` / `scaffold_client`: `{ name|service: string, methods?: Method[] }`
76
+ where `Method = { name, description?, params?: {name,type,description?}[], returns? }`.
77
+
78
+ Every tool returns `{ content: [{ type: "text", text }] }`; errors return the same
79
+ shape with `isError: true` (so the agent sees a message, not a transport failure).
80
+
81
+ ## 5. Distribution to registries
82
+
83
+ Publish `@imqueue/mcp` to npm, then list it everywhere agents discover servers:
84
+
85
+ | Channel | Artifact / action |
86
+ |---|---|
87
+ | **Official MCP registry** | `server.json` (this repo) → publish via `mcp-publisher`. Namespace `io.github.imqueue/mcp`. |
88
+ | **Smithery** | `smithery.yaml` (this repo) → connect the GitHub repo. |
89
+ | **mcp.so / PulseMCP / Glama** | Auto-index from npm + GitHub; submit/claim the listing. |
90
+ | **Cursor / VS Code directories** | Add the `mcpServers` JSON snippet to their community lists. |
91
+ | **awesome-mcp-servers** | PR the repo into the list. |
92
+ | **imqueue.org** | Add an "MCP server" section to `/using-ai-assistants/` with the install snippet. |
93
+
94
+ Install snippet promoted everywhere:
95
+ ```json
96
+ { "mcpServers": { "imqueue": { "command": "npx", "args": ["-y", "@imqueue/mcp"] } } }
97
+ ```
98
+
99
+ ## 6. Verification
100
+
101
+ `npm run smoke` spawns the built server and drives the JSON-RPC handshake:
102
+ `initialize` → `tools/list` (asserts all five) → `tools/call` for `scaffold_service`
103
+ and `list_packages` (offline) and `search_docs` (live). CI can run it on every push.
104
+
105
+ ## 7. Roadmap
106
+
107
+ - **Streamable HTTP** deployment (a hosted endpoint) for zero-install use and for
108
+ hosts that prefer remote servers.
109
+ - **`generate_client` for real** — spin up against a reachable running service and
110
+ return the actual generated client.
111
+ - **Resources** — expose docs pages as MCP *resources* (not just tool results) so
112
+ hosts can surface them in their UI.
113
+ - **Prompts** — ship an "author an @imqueue service" prompt template.
114
+ - **Richer search** — fold in `/blog/search-index.json` topics and light stemming to
115
+ improve recall (e.g. "delayed jobs" → job/scheduling pages).
116
+
117
+ ## 8. Licensing
118
+
119
+ GPL-3.0, matching the framework; commercial licensing via imqueue.com.
package/dist/docs.d.ts ADDED
@@ -0,0 +1,17 @@
1
+ export interface DocEntry {
2
+ title: string;
3
+ url: string;
4
+ description: string;
5
+ section: string;
6
+ }
7
+ /** Fetch + parse /llms.txt into a flat list of doc entries (cached). */
8
+ export declare function loadIndex(): Promise<DocEntry[]>;
9
+ /** Rank doc entries by overlap of query terms with title (weighted), section, description and url. */
10
+ export declare function searchDocs(query: string, limit?: number): Promise<DocEntry[]>;
11
+ /** Resolve a page URL/path to its markdown-mirror URL (`<page-url>index.md`). */
12
+ export declare function mirrorUrl(pageUrl: string): string;
13
+ /** Fetch the full markdown of a doc page by its page URL or path. */
14
+ export declare function getDoc(pageUrl: string): Promise<{
15
+ url: string;
16
+ markdown: string;
17
+ }>;
package/dist/docs.js ADDED
@@ -0,0 +1,103 @@
1
+ // Docs access for the @imqueue MCP server.
2
+ //
3
+ // The docs live on imqueue.org as machine-readable feeds:
4
+ // * /llms.txt — curated index: `## Section` + `- [Title](url): description`
5
+ // * /<page-url>index.md — a plain-markdown mirror of every page
6
+ // * /blog/search-index.json — [{ title, url, summary, topics, ... }]
7
+ //
8
+ // We fetch these at runtime (so the server never ships stale copies) and cache
9
+ // them in-process. Only imqueue.org is ever fetched.
10
+ const SITE = "https://imqueue.org";
11
+ const TTL_MS = 60 * 60 * 1000; // 1h in-process cache
12
+ let indexCache = null;
13
+ function assertImqueueUrl(u) {
14
+ const url = new URL(u, SITE);
15
+ if (url.hostname !== "imqueue.org") {
16
+ throw new Error(`Refusing to fetch non-imqueue.org URL: ${url.href}`);
17
+ }
18
+ return url;
19
+ }
20
+ /** Fetch + parse /llms.txt into a flat list of doc entries (cached). */
21
+ export async function loadIndex() {
22
+ if (indexCache && Date.now() - indexCache.at < TTL_MS)
23
+ return indexCache.entries;
24
+ const res = await fetch(`${SITE}/llms.txt`);
25
+ if (!res.ok)
26
+ throw new Error(`Failed to fetch llms.txt (HTTP ${res.status})`);
27
+ const text = await res.text();
28
+ const entries = [];
29
+ let section = "General";
30
+ for (const line of text.split("\n")) {
31
+ const h = line.match(/^##\s+(.+?)\s*$/);
32
+ if (h) {
33
+ section = h[1].trim();
34
+ continue;
35
+ }
36
+ const m = line.match(/^-\s+\[([^\]]+)\]\(([^)]+)\)(?::\s*(.*))?$/);
37
+ if (m) {
38
+ entries.push({
39
+ title: m[1].trim(),
40
+ url: m[2].trim(),
41
+ description: (m[3] || "").trim(),
42
+ section,
43
+ });
44
+ }
45
+ }
46
+ indexCache = { at: Date.now(), entries };
47
+ return entries;
48
+ }
49
+ const STOP = new Set([
50
+ "the", "a", "an", "and", "or", "of", "to", "in", "for", "on", "with",
51
+ "is", "are", "how", "do", "does", "i", "my", "me", "it", "that", "this",
52
+ ]);
53
+ function tokenize(s) {
54
+ return s
55
+ .toLowerCase()
56
+ .split(/[^a-z0-9@/+.-]+/)
57
+ .filter((t) => t.length > 1 && !STOP.has(t));
58
+ }
59
+ /** Rank doc entries by overlap of query terms with title (weighted), section, description and url. */
60
+ export async function searchDocs(query, limit = 6) {
61
+ const entries = await loadIndex();
62
+ const terms = tokenize(query);
63
+ if (!terms.length)
64
+ return entries.slice(0, limit);
65
+ const scored = entries.map((e) => {
66
+ const title = e.title.toLowerCase();
67
+ const hay = `${e.section} ${e.description} ${e.url}`.toLowerCase();
68
+ let score = 0;
69
+ for (const t of terms) {
70
+ if (title.includes(t))
71
+ score += 3;
72
+ if (hay.includes(t))
73
+ score += 1;
74
+ }
75
+ return { e, score };
76
+ });
77
+ return scored
78
+ .filter((x) => x.score > 0)
79
+ .sort((a, b) => b.score - a.score)
80
+ .slice(0, limit)
81
+ .map((x) => x.e);
82
+ }
83
+ /** Resolve a page URL/path to its markdown-mirror URL (`<page-url>index.md`). */
84
+ export function mirrorUrl(pageUrl) {
85
+ const url = assertImqueueUrl(pageUrl);
86
+ let p = url.pathname;
87
+ if (p.endsWith("index.md"))
88
+ return url.href;
89
+ if (p.endsWith(".md"))
90
+ return url.href;
91
+ if (!p.endsWith("/"))
92
+ p += "/";
93
+ return `${SITE}${p}index.md`;
94
+ }
95
+ /** Fetch the full markdown of a doc page by its page URL or path. */
96
+ export async function getDoc(pageUrl) {
97
+ const mUrl = mirrorUrl(pageUrl);
98
+ const res = await fetch(mUrl);
99
+ if (!res.ok)
100
+ throw new Error(`Failed to fetch ${mUrl} (HTTP ${res.status}). Use search_docs to find a valid page URL.`);
101
+ return { url: mUrl, markdown: await res.text() };
102
+ }
103
+ //# sourceMappingURL=docs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"docs.js","sourceRoot":"","sources":["../src/docs.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,118 @@
1
+ #!/usr/bin/env node
2
+ // @imqueue MCP server — exposes @imqueue docs search and service/client
3
+ // scaffolding to AI coding agents (Claude Code, Cursor, …) over stdio.
4
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
5
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
6
+ import { z } from "zod";
7
+ import { searchDocs, getDoc } from "./docs.js";
8
+ import { renderPackages } from "./packages.js";
9
+ import { scaffoldService, scaffoldClient } from "./scaffold.js";
10
+ const text = (t) => ({ content: [{ type: "text", text: t }] });
11
+ const fail = (e) => ({
12
+ content: [{ type: "text", text: `Error: ${e instanceof Error ? e.message : String(e)}` }],
13
+ isError: true,
14
+ });
15
+ const methodSchema = z
16
+ .object({
17
+ name: z.string().describe("Method name"),
18
+ description: z.string().optional().describe("What the method does"),
19
+ params: z
20
+ .array(z.object({
21
+ name: z.string(),
22
+ type: z.string().describe("TypeScript type, e.g. 'string' or 'number[]'"),
23
+ description: z.string().optional(),
24
+ }))
25
+ .optional(),
26
+ returns: z.string().optional().describe("TypeScript return type WITHOUT Promise<> — e.g. 'User' or 'string'"),
27
+ })
28
+ .strict();
29
+ const server = new McpServer({ name: "imqueue", version: "0.1.0" });
30
+ server.registerTool("search_docs", {
31
+ title: "Search @imqueue documentation",
32
+ description: "Search the official @imqueue docs (guides, tutorial, CLI manual, API reference, articles) and return the most relevant pages with their URLs. Use this first when asked how to do something in @imqueue, then get_doc to read a page in full.",
33
+ inputSchema: {
34
+ query: z.string().describe("What you want to find, e.g. 'expose a service method' or 'delayed jobs'"),
35
+ limit: z.number().int().min(1).max(20).optional().describe("Max results (default 6)"),
36
+ },
37
+ }, async ({ query, limit }) => {
38
+ try {
39
+ const hits = await searchDocs(query, limit ?? 6);
40
+ if (!hits.length)
41
+ return text(`No matches for "${query}". Try broader terms or call list_packages.`);
42
+ const body = hits
43
+ .map((h) => `### ${h.title} _(${h.section})_\n${h.description}\n${h.url}`)
44
+ .join("\n\n");
45
+ return text(`${hits.length} result(s) for "${query}":\n\n${body}\n\nRead any page in full with get_doc(url).`);
46
+ }
47
+ catch (e) {
48
+ return fail(e);
49
+ }
50
+ });
51
+ server.registerTool("get_doc", {
52
+ title: "Read an @imqueue doc page",
53
+ description: "Fetch the full markdown of an @imqueue documentation page by its URL (as returned by search_docs). Returns plain markdown suitable for reading and quoting.",
54
+ inputSchema: {
55
+ url: z.string().describe("An imqueue.org page URL, e.g. https://imqueue.org/get-started/"),
56
+ },
57
+ }, async ({ url }) => {
58
+ try {
59
+ const doc = await getDoc(url);
60
+ return text(`Source: ${doc.url}\n\n${doc.markdown}`);
61
+ }
62
+ catch (e) {
63
+ return fail(e);
64
+ }
65
+ });
66
+ server.registerTool("list_packages", {
67
+ title: "List @imqueue packages",
68
+ description: "Return the main @imqueue packages with a one-line summary and install command, so you can pick the right one.",
69
+ inputSchema: {},
70
+ }, async () => {
71
+ try {
72
+ return text(renderPackages());
73
+ }
74
+ catch (e) {
75
+ return fail(e);
76
+ }
77
+ });
78
+ server.registerTool("scaffold_service", {
79
+ title: "Scaffold an @imqueue service",
80
+ description: "Generate an idiomatic @imqueue/rpc service (an IMQService subclass with @expose()d, JSDoc-typed methods) plus a bootstrap that starts it. Provide the methods you want, or omit them for a starter template.",
81
+ inputSchema: {
82
+ name: z.string().describe("Service name, e.g. 'user' or 'UserService'"),
83
+ methods: z.array(methodSchema).optional().describe("Methods to expose"),
84
+ },
85
+ }, async ({ name, methods }) => {
86
+ try {
87
+ return text(scaffoldService(name, methods));
88
+ }
89
+ catch (e) {
90
+ return fail(e);
91
+ }
92
+ });
93
+ server.registerTool("scaffold_client", {
94
+ title: "Scaffold an @imqueue typed client",
95
+ description: "Show how to generate and use the fully-typed client for an @imqueue service. @imqueue generates the real client from a running service (via `imq client generate`), so this returns that command plus an illustrative usage snippet.",
96
+ inputSchema: {
97
+ service: z.string().describe("The service to call, e.g. 'user' or 'UserService'"),
98
+ methods: z.array(methodSchema).optional().describe("Known methods (used to shape the example call)"),
99
+ },
100
+ }, async ({ service, methods }) => {
101
+ try {
102
+ return text(scaffoldClient(service, methods));
103
+ }
104
+ catch (e) {
105
+ return fail(e);
106
+ }
107
+ });
108
+ async function main() {
109
+ const transport = new StdioServerTransport();
110
+ await server.connect(transport);
111
+ // stderr is safe for logs; stdout is the JSON-RPC channel.
112
+ console.error("@imqueue MCP server running on stdio");
113
+ }
114
+ main().catch((err) => {
115
+ console.error("Fatal:", err);
116
+ process.exit(1);
117
+ });
118
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ export interface PkgInfo {
2
+ name: string;
3
+ install: string;
4
+ summary: string;
5
+ }
6
+ export declare const PACKAGES: PkgInfo[];
7
+ export declare function renderPackages(): string;
@@ -0,0 +1,18 @@
1
+ // Static catalog of the main @imqueue packages, so an agent can pick the right
2
+ // one before scaffolding. Kept deliberately short — the full ecosystem lives on
3
+ // imqueue.org and is reachable via search_docs.
4
+ export const PACKAGES = [
5
+ { name: "@imqueue/rpc", install: "npm i @imqueue/rpc", summary: "Type-safe RPC over a message queue — decorators, services and generated clients. The package you build services with." },
6
+ { name: "@imqueue/core", install: "npm i @imqueue/core", summary: "The Redis-backed messaging-queue engine shared by the framework (usually a transitive dependency of rpc)." },
7
+ { name: "@imqueue/cli", install: "npm i -g @imqueue/cli", summary: "The `imq` CLI: scaffolds services, wires VCS/CI/registry providers, generates typed clients and runs a local fleet." },
8
+ { name: "@imqueue/job", install: "npm i @imqueue/job", summary: "Simple, safe-by-default Redis job queue — delayed/scheduled jobs, guaranteed processing, retries." },
9
+ { name: "@imqueue/pg-pubsub", install: "npm i @imqueue/pg-pubsub", summary: "Reliable PostgreSQL LISTEN/NOTIFY with inter-process lock support." },
10
+ { name: "@imqueue/pg-cache", install: "npm i @imqueue/pg-cache", summary: "PostgreSQL-managed cache on Redis for @imqueue service methods." },
11
+ { name: "@imqueue/async-logger", install: "npm i @imqueue/async-logger", summary: "Configurable async logger over winston for @imqueue services." },
12
+ { name: "@imqueue/http-protect", install: "npm i @imqueue/http-protect", summary: "HTTP DDoS-protection middleware." },
13
+ ];
14
+ export function renderPackages() {
15
+ const lines = PACKAGES.map((p) => `- **${p.name}** — ${p.summary}\n \`${p.install}\``);
16
+ return `# @imqueue packages\n\n${lines.join("\n")}\n\nFull ecosystem & docs: https://imqueue.org`;
17
+ }
18
+ //# sourceMappingURL=packages.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"packages.js","sourceRoot":"","sources":["../src/packages.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,gFAAgF;AAChF,gDAAgD;AAQhD,MAAM,CAAC,MAAM,QAAQ,GAAc;IACjC,EAAE,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,oBAAoB,EAAE,OAAO,EAAE,uHAAuH,EAAE;IACzL,EAAE,IAAI,EAAE,eAAe,EAAE,OAAO,EAAE,qBAAqB,EAAE,OAAO,EAAE,2GAA2G,EAAE;IAC/K,EAAE,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,uBAAuB,EAAE,OAAO,EAAE,qHAAqH,EAAE;IAC1L,EAAE,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,oBAAoB,EAAE,OAAO,EAAE,mGAAmG,EAAE;IACrK,EAAE,IAAI,EAAE,oBAAoB,EAAE,OAAO,EAAE,0BAA0B,EAAE,OAAO,EAAE,oEAAoE,EAAE;IAClJ,EAAE,IAAI,EAAE,mBAAmB,EAAE,OAAO,EAAE,yBAAyB,EAAE,OAAO,EAAE,iEAAiE,EAAE;IAC7I,EAAE,IAAI,EAAE,uBAAuB,EAAE,OAAO,EAAE,6BAA6B,EAAE,OAAO,EAAE,+DAA+D,EAAE;IACnJ,EAAE,IAAI,EAAE,uBAAuB,EAAE,OAAO,EAAE,6BAA6B,EAAE,OAAO,EAAE,kCAAkC,EAAE;CACvH,CAAC;AAEF,MAAM,UAAU,cAAc;IAC5B,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,IAAI,QAAQ,CAAC,CAAC,OAAO,SAAS,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC;IACxF,OAAO,0BAA0B,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,gDAAgD,CAAC;AACpG,CAAC"}
@@ -0,0 +1,14 @@
1
+ export interface MethodSpec {
2
+ name: string;
3
+ description?: string;
4
+ params?: {
5
+ name: string;
6
+ type: string;
7
+ description?: string;
8
+ }[];
9
+ returns?: string;
10
+ }
11
+ /** Generate an @imqueue/rpc service class + a bootstrap that starts it. */
12
+ export declare function scaffoldService(name: string, methods?: MethodSpec[]): string;
13
+ /** Generate a typed-client usage snippet for a service. */
14
+ export declare function scaffoldClient(service: string, methods?: MethodSpec[]): string;
@@ -0,0 +1,106 @@
1
+ // Code scaffolding for @imqueue — mirrors what `imq service create` /
2
+ // `imq client generate` produce, but as inline templates an agent can drop into
3
+ // a project. @imqueue is decorator-driven and JSDoc is the source of truth for
4
+ // types, so the generated code documents each method with JSDoc.
5
+ function pascal(s) {
6
+ return s
7
+ .replace(/[^a-zA-Z0-9]+/g, " ")
8
+ .trim()
9
+ .split(/\s+/)
10
+ .map((w) => w.charAt(0).toUpperCase() + w.slice(1))
11
+ .join("");
12
+ }
13
+ const DEFAULT_METHODS = [
14
+ {
15
+ name: "hello",
16
+ description: "Example method — replace with your own.",
17
+ params: [{ name: "name", type: "string", description: "Who to greet" }],
18
+ returns: "string",
19
+ },
20
+ ];
21
+ function renderMethod(m) {
22
+ const params = m.params ?? [];
23
+ const ret = m.returns ?? "void";
24
+ const sig = params.map((p) => `${p.name}: ${p.type}`).join(", ");
25
+ const jsdoc = [
26
+ " /**",
27
+ ` * ${m.description ?? m.name}`,
28
+ ...params.map((p) => ` * @param ${p.name} - ${p.description ?? p.type}`),
29
+ ` * @return {Promise<${ret}>}`,
30
+ " */",
31
+ ].join("\n");
32
+ const body = ret === "void"
33
+ ? " // TODO: implement"
34
+ : ` // TODO: implement\n throw new Error('${m.name}() not implemented');`;
35
+ return `${jsdoc}\n @expose()\n public async ${m.name}(${sig}): Promise<${ret}> {\n${body}\n }`;
36
+ }
37
+ /** Generate an @imqueue/rpc service class + a bootstrap that starts it. */
38
+ export function scaffoldService(name, methods) {
39
+ const cls = pascal(name).endsWith("Service") ? pascal(name) : `${pascal(name)}Service`;
40
+ const list = methods && methods.length ? methods : DEFAULT_METHODS;
41
+ const body = list.map(renderMethod).join("\n\n");
42
+ const service = `import { IMQService, expose } from '@imqueue/rpc';
43
+
44
+ export class ${cls} extends IMQService {
45
+ ${body}
46
+ }
47
+ `;
48
+ const bootstrap = `import { ${cls} } from './${cls}';
49
+
50
+ // Start the service so other services can call its @expose()d methods.
51
+ (async () => {
52
+ const service = new ${cls}({ name: '${cls}' });
53
+ await service.start();
54
+ console.log('${cls} is up');
55
+ })();
56
+ `;
57
+ return [
58
+ `Install: \`npm i @imqueue/rpc\` (needs a running Redis).`,
59
+ "",
60
+ `**${cls}.ts**`,
61
+ "```typescript",
62
+ service.trimEnd(),
63
+ "```",
64
+ "",
65
+ `**index.ts** (bootstrap)`,
66
+ "```typescript",
67
+ bootstrap.trimEnd(),
68
+ "```",
69
+ "",
70
+ `Tip: scaffold a full, provider-wired project (VCS/CI/Docker) with the CLI instead: \`imq service create ${name}\`.`,
71
+ ].join("\n");
72
+ }
73
+ /** Generate a typed-client usage snippet for a service. */
74
+ export function scaffoldClient(service, methods) {
75
+ const cls = pascal(service).endsWith("Service") ? pascal(service) : `${pascal(service)}Service`;
76
+ const clientCls = cls.replace(/Service$/, "Client");
77
+ const sample = (methods && methods[0]) || DEFAULT_METHODS[0];
78
+ const args = (sample.params ?? []).map((p) => `/* ${p.name}: ${p.type} */`).join(", ");
79
+ const usage = `import { ${clientCls} } from './clients/${clientCls}';
80
+
81
+ (async () => {
82
+ const client = new ${clientCls}();
83
+ await client.start();
84
+
85
+ // Fully-typed remote call — signature comes from ${cls}:
86
+ const result = await client.${sample.name}(${args});
87
+ console.log(result);
88
+ })();
89
+ `;
90
+ return [
91
+ `@imqueue generates the **real**, fully-typed client from a **running** service, so its types can never drift:`,
92
+ "",
93
+ "```bash",
94
+ `# with ${cls} running:`,
95
+ `imq client generate ${cls.replace(/Service$/, "")}`,
96
+ "```",
97
+ "",
98
+ `That emits \`./clients/${clientCls}\`. Use it like:`,
99
+ "```typescript",
100
+ usage.trimEnd(),
101
+ "```",
102
+ "",
103
+ `The snippet above is illustrative — prefer the generated client so method signatures stay in sync with the service.`,
104
+ ].join("\n");
105
+ }
106
+ //# sourceMappingURL=scaffold.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scaffold.js","sourceRoot":"","sources":["../src/scaffold.ts"],"names":[],"mappings":"AAAA,sEAAsE;AACtE,gFAAgF;AAChF,+EAA+E;AAC/E,iEAAiE;AASjE,SAAS,MAAM,CAAC,CAAS;IACvB,OAAO,CAAC;SACL,OAAO,CAAC,gBAAgB,EAAE,GAAG,CAAC;SAC9B,IAAI,EAAE;SACN,KAAK,CAAC,KAAK,CAAC;SACZ,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;SAClD,IAAI,CAAC,EAAE,CAAC,CAAC;AACd,CAAC;AAED,MAAM,eAAe,GAAiB;IACpC;QACE,IAAI,EAAE,OAAO;QACb,WAAW,EAAE,yCAAyC;QACtD,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,cAAc,EAAE,CAAC;QACvE,OAAO,EAAE,QAAQ;KAClB;CACF,CAAC;AAEF,SAAS,YAAY,CAAC,CAAa;IACjC,MAAM,MAAM,GAAG,CAAC,CAAC,MAAM,IAAI,EAAE,CAAC;IAC9B,MAAM,GAAG,GAAG,CAAC,CAAC,OAAO,IAAI,MAAM,CAAC;IAChC,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACjE,MAAM,KAAK,GAAG;QACZ,SAAS;QACT,UAAU,CAAC,CAAC,WAAW,IAAI,CAAC,CAAC,IAAI,EAAE;QACnC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC,WAAW,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC;QAC5E,2BAA2B,GAAG,IAAI;QAClC,SAAS;KACV,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACb,MAAM,IAAI,GACR,GAAG,KAAK,MAAM;QACZ,CAAC,CAAC,4BAA4B;QAC9B,CAAC,CAAC,wDAAwD,CAAC,CAAC,IAAI,uBAAuB,CAAC;IAC5F,OAAO,GAAG,KAAK,qCAAqC,CAAC,CAAC,IAAI,IAAI,GAAG,cAAc,GAAG,QAAQ,IAAI,SAAS,CAAC;AAC1G,CAAC;AAED,2EAA2E;AAC3E,MAAM,UAAU,eAAe,CAAC,IAAY,EAAE,OAAsB;IAClE,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC;IACvF,MAAM,IAAI,GAAG,OAAO,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC;IACnE,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAEjD,MAAM,OAAO,GAAG;;eAEH,GAAG;EAChB,IAAI;;CAEL,CAAC;IAEA,MAAM,SAAS,GAAG,YAAY,GAAG,cAAc,GAAG;;;;0BAI1B,GAAG,aAAa,GAAG;;mBAE1B,GAAG;;CAErB,CAAC;IAEA,OAAO;QACL,0DAA0D;QAC1D,EAAE;QACF,KAAK,GAAG,OAAO;QACf,eAAe;QACf,OAAO,CAAC,OAAO,EAAE;QACjB,KAAK;QACL,EAAE;QACF,0BAA0B;QAC1B,eAAe;QACf,SAAS,CAAC,OAAO,EAAE;QACnB,KAAK;QACL,EAAE;QACF,2GAA2G,IAAI,KAAK;KACrH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC;AAED,2DAA2D;AAC3D,MAAM,UAAU,cAAc,CAAC,OAAe,EAAE,OAAsB;IACpE,MAAM,GAAG,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC;IAChG,MAAM,SAAS,GAAG,GAAG,CAAC,OAAO,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;IACpD,MAAM,MAAM,GAAG,CAAC,OAAO,IAAI,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,eAAe,CAAC,CAAC,CAAC,CAAC;IAC7D,MAAM,IAAI,GAAG,CAAC,MAAM,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAEvF,MAAM,KAAK,GAAG,YAAY,SAAS,sBAAsB,SAAS;;;yBAG3C,SAAS;;;wDAGsB,GAAG;kCACzB,MAAM,CAAC,IAAI,IAAI,IAAI;;;CAGpD,CAAC;IAEA,OAAO;QACL,+GAA+G;QAC/G,EAAE;QACF,SAAS;QACT,UAAU,GAAG,WAAW;QACxB,uBAAuB,GAAG,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,EAAE;QACpD,KAAK;QACL,EAAE;QACF,0BAA0B,SAAS,kBAAkB;QACrD,eAAe;QACf,KAAK,CAAC,OAAO,EAAE;QACf,KAAK;QACL,EAAE;QACF,qHAAqH;KACtH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC"}
package/package.json ADDED
@@ -0,0 +1,52 @@
1
+ {
2
+ "name": "@imqueue/mcp",
3
+ "version": "1.0.0",
4
+ "description": "Model Context Protocol server for @imqueue — lets AI coding agents search the docs and scaffold typed services & clients.",
5
+ "keywords": [
6
+ "mcp",
7
+ "model-context-protocol",
8
+ "imqueue",
9
+ "ai",
10
+ "coding-assistant",
11
+ "cursor",
12
+ "claude",
13
+ "rpc",
14
+ "microservices",
15
+ "nodejs",
16
+ "typescript"
17
+ ],
18
+ "homepage": "https://imqueue.org",
19
+ "repository": {
20
+ "type": "git",
21
+ "url": "git+https://github.com/imqueue/mcp.git"
22
+ },
23
+ "license": "GPL-3.0",
24
+ "author": "imqueue.com <support@imqueue.com>",
25
+ "type": "module",
26
+ "bin": {
27
+ "imqueue-mcp": "dist/index.js"
28
+ },
29
+ "files": [
30
+ "dist",
31
+ "SPEC.md"
32
+ ],
33
+ "engines": {
34
+ "node": ">=18"
35
+ },
36
+ "scripts": {
37
+ "build": "tsc",
38
+ "start": "node dist/index.js",
39
+ "dev": "tsx src/index.ts",
40
+ "smoke": "node scripts/smoke.mjs",
41
+ "prepublishOnly": "npm run build"
42
+ },
43
+ "dependencies": {
44
+ "@modelcontextprotocol/sdk": "^1.12.0",
45
+ "zod": "^3.23.8"
46
+ },
47
+ "devDependencies": {
48
+ "@types/node": "^22.0.0",
49
+ "tsx": "^4.19.0",
50
+ "typescript": "^5.6.0"
51
+ }
52
+ }