@digilac/simap-mcp
Advanced tools
@@ -10,3 +10,3 @@ /** | ||
| import { getTranslation } from "../../utils/translation.js"; | ||
| import { escapeInlineCode } from "../../utils/formatting.js"; | ||
| import { formatInlineCode } from "../../utils/formatting.js"; | ||
| import { toToolErrorResult } from "../../utils/errors.js"; | ||
@@ -39,3 +39,3 @@ /** | ||
| type: "text", | ||
| text: `No BKP codes found for \`${escapeInlineCode(query)}\`.`, | ||
| text: `No BKP codes found for ${formatInlineCode(query)}.`, | ||
| }, | ||
@@ -45,3 +45,3 @@ ], | ||
| } | ||
| let result = `# BKP Codes for \`${escapeInlineCode(query)}\`\n\n`; | ||
| let result = `# BKP Codes for ${formatInlineCode(query)}\n\n`; | ||
| result += `${data.codes.length} result(s) found.\n\n`; | ||
@@ -48,0 +48,0 @@ for (const item of data.codes) { |
@@ -10,3 +10,3 @@ /** | ||
| import { getTranslation } from "../../utils/translation.js"; | ||
| import { escapeInlineCode } from "../../utils/formatting.js"; | ||
| import { formatInlineCode } from "../../utils/formatting.js"; | ||
| import { toToolErrorResult } from "../../utils/errors.js"; | ||
@@ -51,3 +51,3 @@ /** | ||
| type: "text", | ||
| text: `No CPV codes found for \`${escapeInlineCode(query)}\`.`, | ||
| text: `No CPV codes found for ${formatInlineCode(query)}.`, | ||
| }, | ||
@@ -59,3 +59,3 @@ ], | ||
| const flatCodes = flattenCodes(data.codes); | ||
| let result = `# CPV Codes for \`${escapeInlineCode(query)}\`\n\n`; | ||
| let result = `# CPV Codes for ${formatInlineCode(query)}\n\n`; | ||
| result += `${flatCodes.length} result(s) found.\n\n`; | ||
@@ -62,0 +62,0 @@ for (const item of flatCodes) { |
@@ -10,3 +10,3 @@ /** | ||
| import { getTranslation } from "../../utils/translation.js"; | ||
| import { escapeInlineCode } from "../../utils/formatting.js"; | ||
| import { formatInlineCode } from "../../utils/formatting.js"; | ||
| import { toToolErrorResult } from "../../utils/errors.js"; | ||
@@ -39,3 +39,3 @@ /** | ||
| type: "text", | ||
| text: `No NPK codes found for \`${escapeInlineCode(query)}\`.`, | ||
| text: `No NPK codes found for ${formatInlineCode(query)}.`, | ||
| }, | ||
@@ -45,3 +45,3 @@ ], | ||
| } | ||
| let result = `# NPK Codes for \`${escapeInlineCode(query)}\`\n\n`; | ||
| let result = `# NPK Codes for ${formatInlineCode(query)}\n\n`; | ||
| result += `${data.codes.length} result(s) found.\n\n`; | ||
@@ -48,0 +48,0 @@ for (const item of data.codes) { |
@@ -10,3 +10,3 @@ /** | ||
| import { getTranslation } from "../../utils/translation.js"; | ||
| import { escapeInlineCode } from "../../utils/formatting.js"; | ||
| import { formatInlineCode } from "../../utils/formatting.js"; | ||
| import { toToolErrorResult } from "../../utils/errors.js"; | ||
@@ -39,3 +39,3 @@ /** | ||
| type: "text", | ||
| text: `No OAG codes found for \`${escapeInlineCode(query)}\`.`, | ||
| text: `No OAG codes found for ${formatInlineCode(query)}.`, | ||
| }, | ||
@@ -45,3 +45,3 @@ ], | ||
| } | ||
| let result = `# OAG Codes for \`${escapeInlineCode(query)}\`\n\n`; | ||
| let result = `# OAG Codes for ${formatInlineCode(query)}\n\n`; | ||
| result += `${data.codes.length} result(s) found.\n\n`; | ||
@@ -48,0 +48,0 @@ for (const item of data.codes) { |
@@ -10,3 +10,3 @@ /** | ||
| import { getTranslation } from "../../utils/translation.js"; | ||
| import { escapeInlineCode } from "../../utils/formatting.js"; | ||
| import { formatInlineCode } from "../../utils/formatting.js"; | ||
| import { toToolErrorResult } from "../../utils/errors.js"; | ||
@@ -73,3 +73,3 @@ /** | ||
| type: "text", | ||
| text: `No institutions found for \`${escapeInlineCode(search)}\`.`, | ||
| text: `No institutions found for ${formatInlineCode(search)}.`, | ||
| }, | ||
@@ -80,3 +80,3 @@ ], | ||
| let result = search | ||
| ? `# Public Institutions for \`${escapeInlineCode(search)}\`\n\n` | ||
| ? `# Public Institutions for ${formatInlineCode(search)}\n\n` | ||
| : `# Public Institutions\n\n`; | ||
@@ -83,0 +83,0 @@ result += `${institutions.length} institution(s) found.\n\n`; |
@@ -9,3 +9,3 @@ /** | ||
| import { ProcOfficesPublicResponseSchema } from "../../types/schemas.js"; | ||
| import { escapeInlineCode } from "../../utils/formatting.js"; | ||
| import { formatInlineCode } from "../../utils/formatting.js"; | ||
| import { toToolErrorResult } from "../../utils/errors.js"; | ||
@@ -77,3 +77,3 @@ /** | ||
| if (!data.procOffices || data.procOffices.length === 0) { | ||
| const searchDesc = search ? ` for \`${escapeInlineCode(search)}\`` : ""; | ||
| const searchDesc = search ? ` for ${formatInlineCode(search)}` : ""; | ||
| return { | ||
@@ -89,3 +89,3 @@ content: [ | ||
| let result = search | ||
| ? `# Procurement Offices for \`${escapeInlineCode(search)}\`\n\n` | ||
| ? `# Procurement Offices for ${formatInlineCode(search)}\n\n` | ||
| : `# Procurement Offices\n\n`; | ||
@@ -92,0 +92,0 @@ result += `${data.procOffices.length} office(s) found.\n\n`; |
@@ -7,7 +7,36 @@ /** | ||
| /** | ||
| * Escapes user input for safe embedding in inline Markdown code spans. | ||
| * Strips newlines and escapes backticks. | ||
| * Defensively escapes user input for embedding into inline Markdown *prose* | ||
| * (i.e. plain text in list items, paragraphs — NOT inside a code span). | ||
| * | ||
| * Backslashes must be escaped before backticks: otherwise input like `` \` `` | ||
| * would become `` \\` ``, which Markdown reads as a literal `\` followed by an | ||
| * un-escaped backtick. Newlines are collapsed to spaces. | ||
| * | ||
| * For embedding inside a code span, use {@link formatInlineCode} instead — | ||
| * CommonMark treats backslashes as literal inside code spans, so backslash | ||
| * escaping does nothing there. | ||
| */ | ||
| export declare function escapeInlineCode(value: string): string; | ||
| /** | ||
| * Wraps user input in a CommonMark-safe inline code span. | ||
| * | ||
| * Per CommonMark §6.1, a code span is delimited by backtick runs of equal | ||
| * length, and a backtick run inside the content cannot match the fence. We | ||
| * pick a fence one longer than the longest run of backticks in `value`, and | ||
| * pad with a single space if the content starts or ends with a backtick (the | ||
| * pad is stripped by the parser when the content has any non-space char, so | ||
| * the rendering is unaffected). | ||
| * | ||
| * Newlines are collapsed to spaces; the renderer would do this anyway, but | ||
| * doing it here keeps tool output predictable when concatenated into | ||
| * multi-line blocks. | ||
| * | ||
| * Examples: | ||
| * formatInlineCode("foo") → "`foo`" | ||
| * formatInlineCode("a`b") → "``a`b``" | ||
| * formatInlineCode("`x`") → "`` `x` ``" | ||
| * formatInlineCode("a``b") → "```a``b```" | ||
| */ | ||
| export declare function formatInlineCode(value: string): string; | ||
| /** | ||
| * Builds the simap.ch URL for a project. | ||
@@ -14,0 +43,0 @@ */ |
@@ -7,9 +7,50 @@ /** | ||
| /** | ||
| * Escapes user input for safe embedding in inline Markdown code spans. | ||
| * Strips newlines and escapes backticks. | ||
| * Defensively escapes user input for embedding into inline Markdown *prose* | ||
| * (i.e. plain text in list items, paragraphs — NOT inside a code span). | ||
| * | ||
| * Backslashes must be escaped before backticks: otherwise input like `` \` `` | ||
| * would become `` \\` ``, which Markdown reads as a literal `\` followed by an | ||
| * un-escaped backtick. Newlines are collapsed to spaces. | ||
| * | ||
| * For embedding inside a code span, use {@link formatInlineCode} instead — | ||
| * CommonMark treats backslashes as literal inside code spans, so backslash | ||
| * escaping does nothing there. | ||
| */ | ||
| export function escapeInlineCode(value) { | ||
| return value.replace(/[`]/g, "\\`").replace(/[\r\n]+/g, " "); | ||
| return value | ||
| .replace(/\\/g, "\\\\") | ||
| .replace(/`/g, "\\`") | ||
| .replace(/[\r\n]+/g, " "); | ||
| } | ||
| /** | ||
| * Wraps user input in a CommonMark-safe inline code span. | ||
| * | ||
| * Per CommonMark §6.1, a code span is delimited by backtick runs of equal | ||
| * length, and a backtick run inside the content cannot match the fence. We | ||
| * pick a fence one longer than the longest run of backticks in `value`, and | ||
| * pad with a single space if the content starts or ends with a backtick (the | ||
| * pad is stripped by the parser when the content has any non-space char, so | ||
| * the rendering is unaffected). | ||
| * | ||
| * Newlines are collapsed to spaces; the renderer would do this anyway, but | ||
| * doing it here keeps tool output predictable when concatenated into | ||
| * multi-line blocks. | ||
| * | ||
| * Examples: | ||
| * formatInlineCode("foo") → "`foo`" | ||
| * formatInlineCode("a`b") → "``a`b``" | ||
| * formatInlineCode("`x`") → "`` `x` ``" | ||
| * formatInlineCode("a``b") → "```a``b```" | ||
| */ | ||
| export function formatInlineCode(value) { | ||
| const cleaned = value.replace(/[\r\n]+/g, " "); | ||
| if (cleaned === "") | ||
| return "` `"; | ||
| const runs = cleaned.match(/`+/g) ?? []; | ||
| const longestRun = runs.reduce((m, r) => Math.max(m, r.length), 0); | ||
| const fence = "`".repeat(longestRun + 1); | ||
| const pad = cleaned.startsWith("`") || cleaned.endsWith("`") ? " " : ""; | ||
| return `${fence}${pad}${cleaned}${pad}${fence}`; | ||
| } | ||
| /** | ||
| * Builds the simap.ch URL for a project. | ||
@@ -16,0 +57,0 @@ */ |
+1
-1
| { | ||
| "name": "@digilac/simap-mcp", | ||
| "version": "1.2.2", | ||
| "version": "1.2.3", | ||
| "mcpName": "io.github.Digilac/simap-mcp", | ||
@@ -5,0 +5,0 @@ "description": "MCP server for simap.ch - Swiss public procurement platform", |
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
156702
2.05%4197
1.7%