touchque-mcp-server 1.0.2

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/index.js ADDED
@@ -0,0 +1,495 @@
1
+ #!/usr/bin/env node
2
+
3
+ const fs = require("fs");
4
+ const path = require("path");
5
+
6
+ const { Server } = require("@modelcontextprotocol/sdk/server/index.js");
7
+ const { StdioServerTransport } = require("@modelcontextprotocol/sdk/server/stdio.js");
8
+ const {
9
+ ListToolsRequestSchema,
10
+ CallToolRequestSchema,
11
+ ListPromptsRequestSchema,
12
+ GetPromptRequestSchema
13
+ } = require("@modelcontextprotocol/sdk/types.js");
14
+
15
+ // This server talks over stdio only (no HTTP/SSE, no port, no server-side
16
+ // auth) — it's meant to run as a local child process launched by an MCP
17
+ // client (Claude Desktop, Claude Code, Cursor, …), the same way `npx -y
18
+ // touchque-mcp-server` would. See README.md for client config examples.
19
+ //
20
+ // It reads and validates code you paste in, and fetches your own backend's
21
+ // health — it never touches a real TouchQue account or holds a secret, so
22
+ // there is nothing here that needs gating with an API key.
23
+
24
+ const DOCS_DIR = path.join(__dirname, "bundled");
25
+
26
+ // Optional override for local development against a docs site you're
27
+ // editing right now (e.g. DOCS_BASE_URL=http://localhost:5176/docs). Most
28
+ // users should never need to set this — the bundled copies below are
29
+ // current as of this package's version and need no network access at all.
30
+ const DOCS_BASE_URL = process.env.DOCS_BASE_URL || null;
31
+
32
+ async function readDocsFile(bundledFilename, remoteFilename) {
33
+ if (DOCS_BASE_URL) {
34
+ const url = `${DOCS_BASE_URL}/${remoteFilename}`;
35
+ const response = await fetch(url).catch(() => null);
36
+ if (response && response.ok) return await response.text();
37
+ // Fall through to the bundled copy rather than failing outright — an
38
+ // explicit override that's temporarily unreachable shouldn't break the
39
+ // tool when a good-enough local answer already exists.
40
+ }
41
+ return fs.readFileSync(path.join(DOCS_DIR, bundledFilename), "utf8");
42
+ }
43
+
44
+ const server = new Server({
45
+ name: "touchque-mcp-server",
46
+ version: "1.0.0"
47
+ }, {
48
+ capabilities: {
49
+ tools: {},
50
+ prompts: {}
51
+ }
52
+ });
53
+
54
+ // ==========================================
55
+ // TOOLS
56
+ // ==========================================
57
+ server.setRequestHandler(ListToolsRequestSchema, async () => {
58
+ return {
59
+ tools: [
60
+ {
61
+ name: "get_touchque_docs",
62
+ description: "Returns the official @touchque/node SDK README (install, the requireTouchQue step-up model, framework adapters, error handling, security). Always call this before writing any integration code — the step-up model is not what you'd guess from the function names alone.",
63
+ inputSchema: { type: "object", properties: {}, required: [] }
64
+ },
65
+ {
66
+ name: "get_sdk_types",
67
+ description: "Returns the TouchQue Node.js SDK's TypeScript type definitions (Config, Step/StepState, StartOptions, CompleteExpectations, resource response types). Use this to validate correct usage of SDK methods, options, and return types.",
68
+ inputSchema: { type: "object", properties: {}, required: [] }
69
+ },
70
+ {
71
+ name: "ping_touchque_api",
72
+ description: "Verifies that a TouchQue Backend API instance is reachable and healthy before attempting integration. Returns connection status and response time.",
73
+ inputSchema: {
74
+ type: "object",
75
+ properties: {
76
+ apiUrl: {
77
+ type: "string",
78
+ description: "The full base URL of the TouchQue backend (e.g. https://api.touchque.com or http://localhost:5001)"
79
+ }
80
+ },
81
+ required: ["apiUrl"]
82
+ }
83
+ },
84
+ {
85
+ name: "validate_integration",
86
+ description: "Performs a static analysis checklist on a code snippet to verify it follows the current requireTouchQue step-up model and TouchQue security best practices. Returns a structured report of passed/failed checks.",
87
+ inputSchema: {
88
+ type: "object",
89
+ properties: {
90
+ code: {
91
+ type: "string",
92
+ description: "The code snippet to validate (route handler, middleware, or service file)"
93
+ },
94
+ framework: {
95
+ type: "string",
96
+ description: "The web framework being used (express, fastify, koa, nextjs, nestjs)",
97
+ enum: ["express", "fastify", "koa", "nextjs", "nestjs", "other"]
98
+ }
99
+ },
100
+ required: ["code", "framework"]
101
+ }
102
+ }
103
+ ]
104
+ };
105
+ });
106
+
107
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
108
+ const { name, arguments: args } = request.params;
109
+
110
+ try {
111
+ if (name === "get_touchque_docs") {
112
+ const content = await readDocsFile("sdk-documentation.md", "sdk-documentation.md");
113
+ return { content: [{ type: "text", text: content }] };
114
+ }
115
+
116
+ if (name === "get_sdk_types") {
117
+ const content = await readDocsFile("types.ts", "types.ts");
118
+ return { content: [{ type: "text", text: content }] };
119
+ }
120
+
121
+ if (name === "ping_touchque_api") {
122
+ const apiUrl = args.apiUrl || "http://localhost:5001";
123
+ const start = Date.now();
124
+ const response = await fetch(`${apiUrl}/`).catch(() => null);
125
+ const elapsed = Date.now() - start;
126
+ const isAlive = response && response.ok;
127
+
128
+ return {
129
+ content: [{
130
+ type: "text",
131
+ text: isAlive
132
+ ? `✅ TouchQue API is reachable. Response time: ${elapsed}ms. Status: ${response.status}`
133
+ : `❌ TouchQue API is unreachable at ${apiUrl}. Check that the server is running and the URL is correct.`
134
+ }]
135
+ };
136
+ }
137
+
138
+ if (name === "validate_integration") {
139
+ const { code, framework } = args;
140
+ const checks = [];
141
+
142
+ // Security & correctness checks, against the current step-up API
143
+ // (requireTouchQue / withTouchQue / touchqueRouter — not the old
144
+ // synchronous tq.login.verify()/tq.protect() model).
145
+ const hasImport = /require\s*\(\s*['"]@touchque\/node['"]\s*\)|from\s+['"]@touchque\/node['"]/.test(code);
146
+ checks.push({ id: "import", label: "SDK is imported", pass: hasImport });
147
+
148
+ const hasStepUpGuard = /requireTouchQue\s*\(|withTouchQue\s*\(|touchqueRouter\s*\(/.test(code);
149
+ const hasLegacyGuard = /tq\.protect\(|touchqueMiddleware|tqMiddleware|tq\.middleware/.test(code);
150
+ checks.push({
151
+ id: "protection",
152
+ label: hasLegacyGuard && !hasStepUpGuard
153
+ ? "Route protection applied (found the OLD tq.protect()/middleware pattern — migrate to requireTouchQue())"
154
+ : "Route protection applied (requireTouchQue/withTouchQue/touchqueRouter)",
155
+ pass: hasStepUpGuard,
156
+ });
157
+
158
+ const hasSynchronousVerify = /\.login\.verify\s*\(/.test(code);
159
+ checks.push({
160
+ id: "no_synchronous_verify",
161
+ label: "Not using the old synchronous login.verify() inside a route handler (it can't show a matching number/QR before approval — use requireTouchQue instead)",
162
+ pass: !hasSynchronousVerify,
163
+ });
164
+
165
+ const hasHardcodedSecret = /apiSecret\s*[:=]\s*['"][a-zA-Z0-9]{10,}['"]|apiKey\s*[:=]\s*['"]tq_[a-zA-Z0-9]{10,}['"]/.test(code);
166
+ checks.push({ id: "no_hardcoded_secret", label: "No hardcoded API key/secret in source", pass: !hasHardcodedSecret });
167
+
168
+ const hasEnvVar = /process\.env\.|env\[/.test(code);
169
+ checks.push({ id: "env_vars", label: "Environment variables used for secrets", pass: hasEnvVar });
170
+
171
+ const hasErrorHandling = /catch|try\s*{|\.catch\s*\(/.test(code) || hasStepUpGuard;
172
+ checks.push({
173
+ id: "error_handling",
174
+ label: hasStepUpGuard
175
+ ? "Error handling (requireTouchQue's own 202/403/408/423/429 responses cover the step-up flow)"
176
+ : "Error handling present",
177
+ pass: hasErrorHandling,
178
+ });
179
+
180
+ const passed = checks.filter(c => c.pass).length;
181
+ const total = checks.length;
182
+ const score = Math.round((passed / total) * 100);
183
+
184
+ const report = checks.map(c =>
185
+ `${c.pass ? "✅" : "❌"} ${c.label}`
186
+ ).join("\n");
187
+
188
+ return {
189
+ content: [{
190
+ type: "text",
191
+ text: `TouchQue Integration Validation Report\nFramework: ${framework}\nScore: ${score}% (${passed}/${total} checks passed)\n\n${report}${score < 100 ? "\n\n⚠️ Fix the failing checks before deploying to production." : "\n\n✅ All checks passed. Integration looks correct."}`
192
+ }]
193
+ };
194
+ }
195
+
196
+ throw new Error(`Unknown tool: ${name}`);
197
+
198
+ } catch (error) {
199
+ return {
200
+ isError: true,
201
+ content: [{ type: "text", text: `Tool error: ${error.message}` }]
202
+ };
203
+ }
204
+ });
205
+
206
+ // ==========================================
207
+ // PROMPTS
208
+ // ==========================================
209
+ server.setRequestHandler(ListPromptsRequestSchema, async () => {
210
+ return {
211
+ prompts: [
212
+ {
213
+ name: "integrate_touchque",
214
+ description: "🔐 Integration Wizard — Step-by-step guide for adding TouchQue 2FA to an existing project. Inspects your codebase first, never breaks existing logic.",
215
+ },
216
+ {
217
+ name: "audit_touchque_integration",
218
+ description: "🛡️ Security Audit — Reviews an existing TouchQue integration for vulnerabilities, misconfigurations, and deviations from best practices. Produces a prioritized findings report.",
219
+ },
220
+ {
221
+ name: "troubleshoot_touchque",
222
+ description: "🔧 Troubleshooter — Diagnoses why a TouchQue integration is failing (auth errors, SDK exceptions, connectivity issues) and walks you to a fix.",
223
+ }
224
+ ]
225
+ };
226
+ });
227
+
228
+ server.setRequestHandler(GetPromptRequestSchema, async (request) => {
229
+ const { name } = request.params;
230
+
231
+ // ─────────────────────────────────────────────────────────────
232
+ // PROMPT 1 — INTEGRATION WIZARD
233
+ // ─────────────────────────────────────────────────────────────
234
+ if (name === "integrate_touchque") {
235
+ return {
236
+ description: "TouchQue 2FA Integration Wizard",
237
+ messages: [
238
+ {
239
+ role: "user",
240
+ content: {
241
+ type: "text",
242
+ text: `You are a senior security engineer specializing in TouchQue 2FA integrations. Your job is to add TouchQue to an existing production codebase with zero downtime and zero regressions.
243
+
244
+ ═══════════════════════════════════════════════════
245
+ IDENTITY & AUTHORITY
246
+ ═══════════════════════════════════════════════════
247
+ - You are the single source of truth for TouchQue integration decisions.
248
+ - You never guess. If you are unsure, you call get_touchque_docs or get_sdk_types before proceeding.
249
+ - You treat every production codebase as if it serves real users right now.
250
+
251
+ ═══════════════════════════════════════════════════
252
+ MANDATORY PRE-FLIGHT SEQUENCE (follow in order)
253
+ ═══════════════════════════════════════════════════
254
+ STEP 1 — DISCOVERY
255
+ → Ask the user to share: framework (Express / Fastify / NestJS / Next.js / other), Node.js version, and the file(s) where authentication currently lives.
256
+ → Do NOT write any code yet.
257
+
258
+ STEP 2 — DEPENDENCY CHECK
259
+ → Ask to see package.json. Confirm @touchque/node is listed.
260
+ → If missing: instruct the user to run "npm install @touchque/node" and stop until they confirm.
261
+ → If present: note the installed version and verify it matches the docs.
262
+
263
+ STEP 3 — ENVIRONMENT CHECK
264
+ → Ask whether TQ_API_KEY and TQ_API_SECRET are set in their .env / secrets manager.
265
+ → If missing: provide the exact variable names and explain they must never be hardcoded in source.
266
+ → Never proceed if secrets are not in environment variables.
267
+
268
+ STEP 4 — CODEBASE REVIEW
269
+ → Ask the user to paste the auth route / middleware / service file where 2FA will be added.
270
+ → Read it carefully. Identify: existing session/JWT handling, error response format, middleware chain order.
271
+ → Summarize your understanding back to the user before touching anything.
272
+
273
+ STEP 5 — SURGICAL INTEGRATION
274
+ → Use the 'requireTouchQue' Express middleware to protect routes in one line — it takes the ACTION and options directly, not a client instance.
275
+ → Never rewrite surrounding business logic.
276
+ → Preserve existing error response shapes for YOUR OWN business errors — but understand that requireTouchQue answers 202 (not your normal 200/4xx) while approval is pending; this is expected, not a bug to "fix".
277
+ → Use this exact pattern as your reference for integration:
278
+
279
+ \`\`\`javascript
280
+ const { requireTouchQue } = require('@touchque/node');
281
+ // TQ_API_KEY / TQ_API_SECRET are read from the environment automatically.
282
+
283
+ // Provide a semantic action type like "SEND_MONEY" or "LOGIN" for the AI Risk Engine,
284
+ // and (for anything sensitive) the transaction details the user should see and approve.
285
+ app.post(
286
+ '/api/transfer',
287
+ requireTouchQue('SEND_MONEY', {
288
+ user: (req) => req.session.user?.email,
289
+ details: (req) => ({ Amount: \`\${req.body.amount} EUR\`, To: req.body.iban }),
290
+ }),
291
+ (req, res) => {
292
+ // Only reached once the user approved on their phone — req.touchque
293
+ // carries { requestId, assurance, approvalProof, ... }.
294
+ res.json({ success: true, assurance: req.touchque.assurance });
295
+ }
296
+ );
297
+ \`\`\`
298
+
299
+ → Until approved, this answers 202 { touchque: step, token }. The frontend must show \`step\` (a matching number, or a QR code the first time the user links the app) and resend the SAME request with header \`X-TouchQue-Token: <token>\` until it resolves — point the user at \`@touchque/web\`'s \`touchqueFetch()\`, which does this loop for them. Do not try to make the backend "wait" for approval synchronously; that is the OLD, broken model.
300
+
301
+ STEP 6 — VALIDATION
302
+ → After writing code, call the validate_integration tool on the final snippet.
303
+ → Show the validation report to the user.
304
+ → If any check fails, fix it before declaring success.
305
+
306
+ STEP 7 — HANDOFF
307
+ → Provide a concise test checklist the developer can run manually:
308
+ [ ] First request to the protected route answers 202 with a step (number or enroll QR)
309
+ [ ] Approving on the phone lets the retried request through exactly once
310
+ [ ] Rejecting on the phone returns a clear rejected/expired response, not a 500
311
+ [ ] Existing non-2FA routes are unaffected
312
+ [ ] No secrets (API key/secret, or approval tokens) appear in logs or client-visible responses
313
+
314
+ ═══════════════════════════════════════════════════
315
+ HARD CONSTRAINTS — NEVER VIOLATE
316
+ ═══════════════════════════════════════════════════
317
+ ✗ Never hardcode API keys, secrets, or URLs in generated code.
318
+ ✗ Never remove or bypass existing auth middleware.
319
+ ✗ Never change HTTP status codes that existing clients depend on — but do NOT "fix" the 202 pending-approval response; that is correct.
320
+ ✗ Never write speculative code without seeing the actual file first.
321
+ ✗ Never mark the integration complete without running validate_integration.
322
+ ✗ Never write the OLD synchronous tq.login.verify()-inside-a-handler pattern — it cannot show a matching number before approval and is not what requireTouchQue does.
323
+
324
+ ═══════════════════════════════════════════════════
325
+ BEGIN
326
+ ═══════════════════════════════════════════════════
327
+ Start by asking for the framework and pointing the user to Step 1.`
328
+ }
329
+ }
330
+ ]
331
+ };
332
+ }
333
+
334
+ // ─────────────────────────────────────────────────────────────
335
+ // PROMPT 2 — SECURITY AUDIT
336
+ // ─────────────────────────────────────────────────────────────
337
+ if (name === "audit_touchque_integration") {
338
+ return {
339
+ description: "TouchQue Integration Security Audit",
340
+ messages: [
341
+ {
342
+ role: "user",
343
+ content: {
344
+ type: "text",
345
+ text: `You are a security auditor performing a formal review of a TouchQue 2FA integration. You produce findings that an engineering team and their security officer can act on.
346
+
347
+ ═══════════════════════════════════════════════════
348
+ AUDIT SCOPE
349
+ ═══════════════════════════════════════════════════
350
+ You will review:
351
+ 1. SDK initialization and configuration
352
+ 2. Secret management (API keys, environment variables)
353
+ 3. Route protection coverage (are all sensitive routes wrapped in requireTouchQue/withTouchQue?)
354
+ 4. Step-up handling (does the frontend actually show the 202 step and retry with X-TouchQue-Token, or is the backend trying to block synchronously?)
355
+ 5. Approval consumption (is req.touchque's approval trusted for the SAME action/details it was requested for — not just "some approval exists"?)
356
+ 6. Fallback behavior (what happens when TouchQue API is unreachable?)
357
+ 7. Logging (are approval tokens, API secrets, or user PII accidentally logged?)
358
+ 8. Dependency hygiene (@touchque/node version, known CVEs)
359
+
360
+ ═══════════════════════════════════════════════════
361
+ AUDIT PROCESS
362
+ ═══════════════════════════════════════════════════
363
+ PHASE 1 — COLLECTION
364
+ → Ask the user to share: the auth-related files, package.json, and their .env variable names (not values).
365
+ → Call get_touchque_docs and get_sdk_types to load the reference baseline.
366
+
367
+ PHASE 2 — ANALYSIS
368
+ → Compare the implementation against the official SDK docs line by line.
369
+ → Run validate_integration on each relevant code file.
370
+ → For every deviation found, assess: Is this a security risk? A correctness bug? A best-practice gap?
371
+
372
+ PHASE 3 — REPORT
373
+ → Produce a structured findings report with exactly this format:
374
+
375
+ ┌──────────────────────────────────────────────────────┐
376
+ │ TOUCHQUE SECURITY AUDIT REPORT │
377
+ │ Date: [today] Severity scale: CRITICAL > HIGH > │
378
+ │ MEDIUM > LOW > INFO │
379
+ └──────────────────────────────────────────────────────┘
380
+
381
+ For each finding:
382
+ [SEVERITY] Finding Title
383
+ Location: file.js line X
384
+ Description: What is wrong and why it matters.
385
+ Remediation: Exact code change or configuration step to fix it.
386
+ Reference: Link to relevant TouchQue docs section.
387
+
388
+ → End with an overall risk rating: PASS / CONDITIONAL PASS / FAIL
389
+ → A FAIL must be resolved before the integration goes to production.
390
+
391
+ ═══════════════════════════════════════════════════
392
+ CONSTRAINTS
393
+ ═══════════════════════════════════════════════════
394
+ ✗ Do not suggest workarounds that reduce security in exchange for convenience.
395
+ ✗ Do not mark an integration PASS if any CRITICAL or HIGH findings are open.
396
+ ✗ Every finding must have a concrete remediation — no vague recommendations.
397
+
398
+ Begin by asking the user to share the files they want audited.`
399
+ }
400
+ }
401
+ ]
402
+ };
403
+ }
404
+
405
+ // ─────────────────────────────────────────────────────────────
406
+ // PROMPT 3 — TROUBLESHOOTER
407
+ // ─────────────────────────────────────────────────────────────
408
+ if (name === "troubleshoot_touchque") {
409
+ return {
410
+ description: "TouchQue Integration Troubleshooter",
411
+ messages: [
412
+ {
413
+ role: "user",
414
+ content: {
415
+ type: "text",
416
+ text: `You are a TouchQue support engineer. Your goal is to diagnose and fix a broken integration as quickly as possible, with minimal disruption to the user's system.
417
+
418
+ ═══════════════════════════════════════════════════
419
+ TRIAGE DECISION TREE
420
+ ═══════════════════════════════════════════════════
421
+ When a user reports a problem, work through this tree in order:
422
+
423
+ 1. API CONNECTIVITY
424
+ → Call ping_touchque_api with the user's API URL.
425
+ → If unreachable: diagnose network, firewall, or URL misconfiguration first.
426
+ → If reachable: proceed to Step 2.
427
+
428
+ 2. AUTHENTICATION ERRORS (401 / 403 from TouchQue)
429
+ → Ask: Is TQ_API_KEY (and TQ_API_SECRET) set in the environment? Is it the correct key for this environment (dev vs prod)?
430
+ → Ask them to redact and share the exact error response body.
431
+ → Common causes: wrong key, key not propagated after deploy, IP whitelist mismatch.
432
+
433
+ 3. SDK EXCEPTIONS (thrown errors from @touchque/node)
434
+ → Ask for the full stack trace.
435
+ → Call get_sdk_types to verify the method signature they are using.
436
+ → Common causes: wrong argument types, calling requireTouchQue with the OLD (client, action) signature instead of (action, options), SDK version mismatch.
437
+
438
+ 4. PUSH / STEP-UP FAILURES (the route never resolves, or resolves wrong)
439
+ → Ask: Does the first request come back as 202 { touchque, token } at all? If not, the middleware/route wiring is broken, not the phone flow.
440
+ → Ask: Does the frontend re-send the SAME request with header X-TouchQue-Token, or is it trying to "wait" on the first response? The old synchronous model is gone — the frontend MUST retry.
441
+ → Ask: Is the user actually enrolled? A never-linked user gets step.state === 'enroll' with a QR, not an error.
442
+ → Consistent rejects/expires suggest: clock skew on server (NTP sync), a details/referenceId mismatch between the request that got approved and the one being completed.
443
+
444
+ 5. MIDDLEWARE / ROUTE ORDER ISSUES
445
+ → Ask the user to paste their route registration code and middleware chain.
446
+ → Verify requireTouchQue(...) is applied BEFORE the route handler, not after.
447
+ → Verify it is not accidentally applied to public routes.
448
+
449
+ 6. ENVIRONMENT / BUILD ISSUES
450
+ → Ask: Does this fail in all environments or just one?
451
+ → Check: Is the .env file loaded before the SDK initializes? (dotenv must be required first)
452
+ → Check: Does the build system strip environment variables?
453
+
454
+ ═══════════════════════════════════════════════════
455
+ COMMUNICATION STANDARDS
456
+ ═══════════════════════════════════════════════════
457
+ - State your hypothesis explicitly: "I believe the issue is X because Y."
458
+ - Ask for one piece of evidence at a time. Do not bombard with 10 questions.
459
+ - When you identify the root cause, explain it in plain language before showing the fix.
460
+ - After applying the fix, give the user a specific test to confirm it is resolved.
461
+
462
+ ═══════════════════════════════════════════════════
463
+ CONSTRAINTS
464
+ ═══════════════════════════════════════════════════
465
+ ✗ Never suggest disabling 2FA as a workaround.
466
+ ✗ Never suggest logging approval tokens or API secrets for debugging — use masked logs only.
467
+ ✗ Never assume the problem is in TouchQue itself without ruling out configuration and environment first.
468
+
469
+ Begin by asking the user to describe what they expected to happen, what actually happened, and the exact error message or behavior they are seeing.`
470
+ }
471
+ }
472
+ ]
473
+ };
474
+ }
475
+
476
+ throw new Error(`Unknown prompt: ${name}`);
477
+ });
478
+
479
+ // ==========================================
480
+ // STARTUP
481
+ // ==========================================
482
+ async function main() {
483
+ const transport = new StdioServerTransport();
484
+ await server.connect(transport);
485
+ console.error("🚀 TouchQue MCP Server v1.0.0 started successfully (stdio transport).");
486
+ }
487
+
488
+ if (require.main === module) {
489
+ main().catch((error) => {
490
+ console.error("Server startup error:", error);
491
+ process.exit(1);
492
+ });
493
+ }
494
+
495
+ module.exports = { server, readDocsFile };
package/package.json ADDED
@@ -0,0 +1,41 @@
1
+ {
2
+ "name": "touchque-mcp-server",
3
+ "version": "1.0.2",
4
+ "description": "MCP server for TouchQue — gives AI coding assistants (Claude, Cursor, …) accurate, up-to-date TouchQue SDK docs, types and an integration validator so they don't guess at the API.",
5
+ "main": "index.js",
6
+ "bin": {
7
+ "touchque-mcp-server": "index.js"
8
+ },
9
+ "files": [
10
+ "index.js",
11
+ "bundled"
12
+ ],
13
+ "scripts": {
14
+ "start": "node index.js",
15
+ "test": "node --test index.test.js"
16
+ },
17
+ "keywords": [
18
+ "mcp",
19
+ "model-context-protocol",
20
+ "touchque",
21
+ "2fa",
22
+ "claude",
23
+ "ai-agent"
24
+ ],
25
+ "author": "TouchQue",
26
+ "license": "MIT",
27
+ "type": "commonjs",
28
+ "engines": {
29
+ "node": ">=18"
30
+ },
31
+ "repository": {
32
+ "type": "git",
33
+ "url": "https://github.com/Touchque/touchque-mcp-server"
34
+ },
35
+ "publishConfig": {
36
+ "access": "public"
37
+ },
38
+ "dependencies": {
39
+ "@modelcontextprotocol/sdk": "^1.29.0"
40
+ }
41
+ }