@supabase/mcp-server-postgrest
v0.1.0MCP server for PostgREST
14
Total
0
Critical
3
High
11
Medium
Findings
unknownDecoded base64 content: ��^��'��m��-��%��d
Detected by automated pattern matching (rule DO-BAS) with medium confidence. May be a false positive.
Report false positiveDecoded base64 content: ��-�����b��܆��
Detected by automated pattern matching (rule DO-BAS) with medium confidence. May be a false positive.
Report false positiveDecoded base64 content: ��^��'��m��-��%��d
Detected by automated pattern matching (rule DO-BAS) with medium confidence. May be a false positive.
Report false positiveJavaScript fetch() call
Detected by automated pattern matching (rule NS-003) with medium confidence. May be a false positive.
>>> 1: import{Server as y}from"@modelcontextprotocol/sdk/server/index.js";import{CallToolRequestSchema as f,ListResourcesRequestSchema as g,ListToolsRequestSchema as T,ReadResourceRequestSchema as S}from"@modelcontextprotocol/sdk/types.js";import{processSql as E,renderHttp as w}from"@supabase/sql-to-rest";import{z as i}from"zod";import{zodToJsonSchema as P}from"zod-to-json-schema";var h="0.1.0";function l(o){return o.endsWith("/")?o:`${o}/`}function d(o){return o.endsWith("/")?o.slice(0,-1):o}var c=class extends y{#s;#e;#r;#t={postgrestRequest:{description:"Performs HTTP request against the PostgREST API",parameters:i.object({method:i.enum(["GET","POST","PUT","PATCH","DELETE"]),path:i.string(),body:i.record(i.unknown()).optional()}),execute:async({method:r,path:t,body:e})=>{let s=new URL(`${this.#s}${t}`);return await(await fetch(s,{method:r,headers:this.#o(r),body:e?JSON.stringify(e):void 0})).json()}},sqlToRest:{description:"Converts SQL query to a PostgREST API request (method, path)",parameters:i.object({sql:i.string()}),execute:async({sql:r})=>{let t=await E(r),e=await w(t);return{method:e.method,path:e.fullPath}}}};constructor(r){super({name:"supabase/postgrest",version:h},{capabilities:{resources:{},tools:{}}}),this.#s=d(r.apiUrl),this.#e=r.apiKey,this.#r=r.schema,this.setRequestHandler(g,async()=>{let t=await this.#n();return{resources:Object.keys(t.paths).filter(s=>s!=="/").map(s=>{let n=s.split("/").pop(),p=t.paths[s].get?.summary;return{uri:new URL(`${s}/spec`,`postgrest://${this.#r}`).href,name:`"${n}" OpenAPI path spec`,description:p,mimeType:"application/json"}})}}),this.setRequestHandler(S,async t=>{let e=await this.#n(),n=new URL(t.params.uri).pathname.split("/"),a=n.pop(),p=n.pop();if(a!=="spec")throw new Error("invalid resource uri");let u=e.paths[`/${p}`];if(!u)throw new Error("path not found");return{contents:[{uri:t.params.uri,mimeType:"application/json",text:JSON.stringify(u)}]}}),this.setRequestHandler(T,async()=>({tools:Object.entries(this.#t).map(([e,{description:s,parameters:n}])=>({name:e,description:s,inputSchema:P(n)}))})),this.setRequestHandler(f,async t=>{let e=this.#t,s=t.params.name;if(!(s in this.#t))throw new Error("tool not found");let n=this.#t[s],a=n.parameters.parse(t.params.arguments);if(!a)throw new Error("missing arguments");let p=await n.execute(a);return{content:[{type:"text",text:JSON.stringify(p)}]}})}async#n(){return await(await fetch(l(this.#s),{headers:this.#o()})).json()}#o(r="GET"){let e={"content-type":"application/json",prefer:"return=representation",[r==="GET"?"accept-profile":"content-profile"]:this.#r};return this.#e&&(e.apikey=this.#e,e.authorization=`Bearer ${this.#e}`),e}};export{c as a};
2: //# sourceMappingURL=chunk-MI2MM4SM.js.mapReport false positiveJavaScript fetch() call
Detected by automated pattern matching (rule NS-003) with medium confidence. May be a false positive.
>>> 1: {"version":3,"sources":["../src/server.ts","../package.json","../src/util.ts"],"sourcesContent":["import { Server } from '@modelcontextprotocol/sdk/server/index.js';\nimport {\n CallToolRequestSchema,\n ListResourcesRequestSchema,\n ListToolsRequestSchema,\n ReadResourceRequestSchema,\n} from '@modelcontextprotocol/sdk/types.js';\nimport { processSql, renderHttp } from '@supabase/sql-to-rest';\nimport { z } from 'zod';\nimport { zodToJsonSchema } from 'zod-to-json-schema';\nimport { version } from '../package.json';\nimport { ensureNoTrailingSlash, ensureTrailingSlash } from './util.js';\n\nexport type PostgrestMcpServerOptions = {\n apiUrl: string;\n apiKey?: string;\n schema: string;\n};\n\nexport default class PostgrestMcpServer extends Server {\n readonly #apiUrl: string;\n readonly #apiKey?: string;\n readonly #schema: string;\n readonly #tools = {\n postgrestRequest: {\n description: 'Performs HTTP request against the PostgREST API',\n parameters: z.object({\n method: z.enum(['GET', 'POST', 'PUT', 'PATCH', 'DELETE']),\n path: z.string(),\n body: z.record(z.unknown()).optional(),\n }),\n execute: async <Body>({\n method,\n path,\n body,\n }: {\n method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';\n path: string;\n body?: Body;\n }) => {\n const url = new URL(`${this.#apiUrl}${path}`);\n\n const response = await fetch(url, {\n method,\n headers: this.#getHeaders(method),\n body: body ? JSON.stringify(body) : undefined,\n });\n\n return await response.json();\n },\n },\n sqlToRest: {\n description:\n 'Converts SQL query to a PostgREST API request (method, path)',\n parameters: z.object({\n sql: z.string(),\n }),\n execute: async ({ sql }: { sql: string }) => {\n const statement = await processSql(sql);\n const request = await renderHttp(statement);\n\n return {\n method: request.method,\n path: request.fullPath,\n };\n },\n },\n };\n\n constructor(options: PostgrestMcpServerOptions) {\n super(\n {\n name: 'supabase/postgrest',\n version,\n },\n {\n capabilities: {\n resources: {},\n tools: {},\n },\n }\n );\n\n this.#apiUrl = ensureNoTrailingSlash(options.apiUrl);\n this.#apiKey = options.apiKey;\n this.#schema = options.schema;\n\n this.setRequestHandler(ListResourcesRequestSchema, async () => {\n const openApiSpec = await this.#fetchOpenApiSpec();\n\n const resources = Object.keys(openApiSpec.paths)\n .filter((path) => path !== '/')\n .map((path) => {\n const name = path.split('/').pop();\n const pathValue = openApiSpec.paths[path];\n const description = pathValue.get?.summary;\n\n return {\n uri: new URL(`${path}/spec`, `postgrest://${this.#schema}`).href,\n name: `\"${name}\" OpenAPI path spec`,\n description,\n mimeType: 'application/json',\n };\n });\n\n return {\n resources,\n };\n });\n\n this.setRequestHandler(ReadResourceRequestSchema, async (request) => {\n const openApiSpec = await this.#fetchOpenApiSpec();\n\n const resourceUrl = new URL(request.params.uri);\n\n const pathComponents = resourceUrl.pathname.split('/');\n const specLiteral = pathComponents.pop();\n const pathName = pathComponents.pop();\n\n if (specLiteral !== 'spec') {\n throw new Error('invalid resource uri');\n }\n\n const pathSpec = openApiSpec.paths[`/${pathName}`];\n\n if (!pathSpec) {\n throw new Error('path not found');\n }\n\n return {\n contents: [\n {\n uri: request.params.uri,\n mimeType: 'application/json',\n text: JSON.stringify(pathSpec),\n },\n ],\n };\n });\n\n this.setRequestHandler(ListToolsRequestSchema, async () => {\n const tools = Object.entries(this.#tools).map(\n ([name, { description, parameters }]) => {\n return {\n name,\n description,\n inputSchema: zodToJsonSchema(parameters),\n };\n }\n );\n\n return {\n tools,\n };\n });\n\n this.setRequestHandler(CallToolRequestSchema, async (request) => {\n const tools = this.#tools;\n const toolName = request.params.name as keyof typeof tools;\n\n if (!(toolName in this.#tools)) {\n throw new Error('tool not found');\n }\n\n const tool = this.#tools[toolName];\n const args = tool.parameters.parse(request.params.arguments);\n\n if (!args) {\n throw new Error('missing arguments');\n }\n\n const result = await tool.execute(args as any);\n\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(result),\n },\n ],\n };\n });\n }\n\n async #fetchOpenApiSpec() {\n const response = await fetch(ensureTrailingSlash(this.#apiUrl), {\n headers: this.#getHeaders(),\n });\n\n return (await response.json()) as any;\n }\n\n #getHeaders(method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' = 'GET') {\n const schemaHeader =\n method === 'GET' ? 'accept-profile' : 'content-profile';\n\n const headers: HeadersInit = {\n 'content-type': 'application/json',\n prefer: 'return=representation',\n [schemaHeader]: this.#schema,\n };\n\n if (this.#apiKey) {\n headers.apikey = this.#apiKey;\n headers.authorization = `Bearer ${this.#apiKey}`;\n }\n\n return headers;\n }\n}\n","{\n \"name\": \"@supabase/mcp-server-postgrest\",\n \"version\": \"0.1.0\",\n \"description\": \"MCP server for PostgREST\",\n \"license\": \"MIT\",\n \"type\": \"module\",\n \"main\": \"dist/index.cjs\",\n \"types\": \"dist/index.d.ts\",\n \"sideEffects\": false,\n \"scripts\": {\n \"build\": \"tsup --clean\",\n \"prepublishOnly\": \"npm run build\",\n \"test\": \"vitest\"\n },\n \"files\": [\n \"dist/**/*\"\n ],\n \"bin\": {\n \"mcp-server-postgrest\": \"./dist/stdio.js\"\n },\n \"exports\": {\n \".\": {\n \"import\": \"./dist/index.js\",\n \"types\": \"./dist/index.d.ts\",\n \"default\": \"./dist/index.cjs\"\n }\n },\n \"dependencies\": {\n \"@modelcontextprotocol/sdk\": \"^1.0.4\",\n \"@supabase/sql-to-rest\": \"^0.1.6\",\n \"zod\": \"^3.24.1\",\n \"zod-to-json-schema\": \"^3.24.1\"\n },\n \"devDependencies\": {\n \"@supabase/mcp-utils\": \"*\",\n \"@total-typescript/tsconfig\": \"^1.0.4\",\n \"@types/node\": \"^22.8.6\",\n \"prettier\": \"^3.3.3\",\n \"tsup\": \"^8.3.5\",\n \"tsx\": \"^4.19.2\",\n \"typescript\": \"^5.6.3\",\n \"vitest\": \"^2.1.4\"\n }\n}\n","/**\n * Ensures that a URL has a trailing slash.\n */\nexport function ensureTrailingSlash(url: string) {\n return url.endsWith('/') ? url : `${url}/`;\n}\n\n/**\n * Ensures that a URL does not have a trailing slash.\n */\nexport function ensureNoTrailingSlash(url: string) {\n return url.endsWith('/') ? url.slice(0, -1) : url;\n}\n"],"mappings":"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","names":["Server","CallToolRequestSchema","ListResourcesRequestSchema","ListToolsRequestSchema","ReadResourceRequestSchema","processSql","renderHttp","z","zodToJsonSchema","version","ensureTrailingSlash","url","ensureNoTrailingSlash","PostgrestMcpServer","Server","#apiUrl","#apiKey","#schema","#tools","z","method","path","body","url","#getHeaders","sql","statement","processSql","request","renderHttp","options","version","ensureNoTrailingSlash","ListResourcesRequestSchema","openApiSpec","#fetchOpenApiSpec","name","description","ReadResourceRequestSchema","pathComponents","specLiteral","pathName","pathSpec","ListToolsRequestSchema","parameters","zodToJsonSchema","CallToolRequestSchema","tools","toolName","tool","args","result","ensureTrailingSlash","headers"]}Report false positiveHigh-entropy string (4.6 bits/char) — possible encoded payload
Detected by automated pattern matching (rule EN-001) with medium confidence. May be a false positive.
Report false positiveHigh-entropy string (4.6 bits/char) — possible encoded payload
Detected by automated pattern matching (rule EN-001) with medium confidence. May be a false positive.
Report false positiveHigh-entropy string (4.7 bits/char) — possible encoded payload
Detected by automated pattern matching (rule EN-001) with medium confidence. May be a false positive.
Report false positiveJavaScript fetch() call
Detected by automated pattern matching (rule NS-003) with medium confidence. May be a false positive.
>>> 1: "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }var _indexjs = require('@modelcontextprotocol/sdk/server/index.js');var _typesjs = require('@modelcontextprotocol/sdk/types.js');var _sqltorest = require('@supabase/sql-to-rest');var _zod = require('zod');var _zodtojsonschema = require('zod-to-json-schema');var h="0.1.0";function l(o){return o.endsWith("/")?o:`${o}/`}function d(o){return o.endsWith("/")?o.slice(0,-1):o}var c=class extends _indexjs.Server{#s;#e;#r;#t={postgrestRequest:{description:"Performs HTTP request against the PostgREST API",parameters:_zod.z.object({method:_zod.z.enum(["GET","POST","PUT","PATCH","DELETE"]),path:_zod.z.string(),body:_zod.z.record(_zod.z.unknown()).optional()}),execute:async({method:r,path:t,body:e})=>{let s=new URL(`${this.#s}${t}`);return await(await fetch(s,{method:r,headers:this.#o(r),body:e?JSON.stringify(e):void 0})).json()}},sqlToRest:{description:"Converts SQL query to a PostgREST API request (method, path)",parameters:_zod.z.object({sql:_zod.z.string()}),execute:async({sql:r})=>{let t=await _sqltorest.processSql.call(void 0, r),e=await _sqltorest.renderHttp.call(void 0, t);return{method:e.method,path:e.fullPath}}}};constructor(r){super({name:"supabase/postgrest",version:h},{capabilities:{resources:{},tools:{}}}),this.#s=d(r.apiUrl),this.#e=r.apiKey,this.#r=r.schema,this.setRequestHandler(_typesjs.ListResourcesRequestSchema,async()=>{let t=await this.#n();return{resources:Object.keys(t.paths).filter(s=>s!=="/").map(s=>{let n=s.split("/").pop(),p=_optionalChain([t, 'access', _ => _.paths, 'access', _2 => _2[s], 'access', _3 => _3.get, 'optionalAccess', _4 => _4.summary]);return{uri:new URL(`${s}/spec`,`postgrest://${this.#r}`).href,name:`"${n}" OpenAPI path spec`,description:p,mimeType:"application/json"}})}}),this.setRequestHandler(_typesjs.ReadResourceRequestSchema,async t=>{let e=await this.#n(),n=new URL(t.params.uri).pathname.split("/"),a=n.pop(),p=n.pop();if(a!=="spec")throw new Error("invalid resource uri");let u=e.paths[`/${p}`];if(!u)throw new Error("path not found");return{contents:[{uri:t.params.uri,mimeType:"application/json",text:JSON.stringify(u)}]}}),this.setRequestHandler(_typesjs.ListToolsRequestSchema,async()=>({tools:Object.entries(this.#t).map(([e,{description:s,parameters:n}])=>({name:e,description:s,inputSchema:_zodtojsonschema.zodToJsonSchema.call(void 0, n)}))})),this.setRequestHandler(_typesjs.CallToolRequestSchema,async t=>{let e=this.#t,s=t.params.name;if(!(s in this.#t))throw new Error("tool not found");let n=this.#t[s],a=n.parameters.parse(t.params.arguments);if(!a)throw new Error("missing arguments");let p=await n.execute(a);return{content:[{type:"text",text:JSON.stringify(p)}]}})}async#n(){return await(await fetch(l(this.#s),{headers:this.#o()})).json()}#o(r="GET"){let e={"content-type":"application/json",prefer:"return=representation",[r==="GET"?"accept-profile":"content-profile"]:this.#r};return this.#e&&(e.apikey=this.#e,e.authorization=`Bearer ${this.#e}`),e}};exports.a = c;
2: //# sourceMappingURL=chunk-NOXTM46O.cjs.mapReport false positiveHigh-entropy string (4.6 bits/char) — possible encoded payload
Detected by automated pattern matching (rule EN-001) with medium confidence. May be a false positive.
Report false positiveHigh-entropy string (4.6 bits/char) — possible encoded payload
Detected by automated pattern matching (rule EN-001) with medium confidence. May be a false positive.
Report false positiveHigh-entropy string (4.6 bits/char) — possible encoded payload
Detected by automated pattern matching (rule EN-001) with medium confidence. May be a false positive.
Report false positiveHigh-entropy string (4.7 bits/char) — possible encoded payload
Detected by automated pattern matching (rule EN-001) with medium confidence. May be a false positive.
Report false positiveJavaScript fetch() call
Detected by automated pattern matching (rule NS-003) with medium confidence. May be a false positive.
>>> 1: {"version":3,"sources":["../src/server.ts","../package.json","../src/util.ts"],"names":["version","ensureTrailingSlash","url"],"mappings":"AAAA,ipBAAuB,6DAMhB,kDACgC,0BACrB,qDACc,ICP9BA,CAAAA,CAAW,OAAA,CCCN,SAASC,CAAAA,CAAoBC,CAAAA,CAAa,CAC/C,OAAOA,CAAAA,CAAI,QAAA,CAAS,GAAG,CAAA,CAAIA,CAAAA,CAAM,CAAA,EAAA","file":"/Users/grichardson/Documents/dev/supabase/mcp-server-supabase/packages/mcp-server-postgrest/dist/chunk-NOXTM46O.cjs","sourcesContent":["import { Server } from '@modelcontextprotocol/sdk/server/index.js';\nimport {\n CallToolRequestSchema,\n ListResourcesRequestSchema,\n ListToolsRequestSchema,\n ReadResourceRequestSchema,\n} from '@modelcontextprotocol/sdk/types.js';\nimport { processSql, renderHttp } from '@supabase/sql-to-rest';\nimport { z } from 'zod';\nimport { zodToJsonSchema } from 'zod-to-json-schema';\nimport { version } from '../package.json';\nimport { ensureNoTrailingSlash, ensureTrailingSlash } from './util.js';\n\nexport type PostgrestMcpServerOptions = {\n apiUrl: string;\n apiKey?: string;\n schema: string;\n};\n\nexport default class PostgrestMcpServer extends Server {\n readonly #apiUrl: string;\n readonly #apiKey?: string;\n readonly #schema: string;\n readonly #tools = {\n postgrestRequest: {\n description: 'Performs HTTP request against the PostgREST API',\n parameters: z.object({\n method: z.enum(['GET', 'POST', 'PUT', 'PATCH', 'DELETE']),\n path: z.string(),\n body: z.record(z.unknown()).optional(),\n }),\n execute: async <Body>({\n method,\n path,\n body,\n }: {\n method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';\n path: string;\n body?: Body;\n }) => {\n const url = new URL(`${this.#apiUrl}${path}`);\n\n const response = await fetch(url, {\n method,\n headers: this.#getHeaders(method),\n body: body ? JSON.stringify(body) : undefined,\n });\n\n return await response.json();\n },\n },\n sqlToRest: {\n description:\n 'Converts SQL query to a PostgREST API request (method, path)',\n parameters: z.object({\n sql: z.string(),\n }),\n execute: async ({ sql }: { sql: string }) => {\n const statement = await processSql(sql);\n const request = await renderHttp(statement);\n\n return {\n method: request.method,\n path: request.fullPath,\n };\n },\n },\n };\n\n constructor(options: PostgrestMcpServerOptions) {\n super(\n {\n name: 'supabase/postgrest',\n version,\n },\n {\n capabilities: {\n resources: {},\n tools: {},\n },\n }\n );\n\n this.#apiUrl = ensureNoTrailingSlash(options.apiUrl);\n this.#apiKey = options.apiKey;\n this.#schema = options.schema;\n\n this.setRequestHandler(ListResourcesRequestSchema, async () => {\n const openApiSpec = await this.#fetchOpenApiSpec();\n\n const resources = Object.keys(openApiSpec.paths)\n .filter((path) => path !== '/')\n .map((path) => {\n const name = path.split('/').pop();\n const pathValue = openApiSpec.paths[path];\n const description = pathValue.get?.summary;\n\n return {\n uri: new URL(`${path}/spec`, `postgrest://${this.#schema}`).href,\n name: `\"${name}\" OpenAPI path spec`,\n description,\n mimeType: 'application/json',\n };\n });\n\n return {\n resources,\n };\n });\n\n this.setRequestHandler(ReadResourceRequestSchema, async (request) => {\n const openApiSpec = await this.#fetchOpenApiSpec();\n\n const resourceUrl = new URL(request.params.uri);\n\n const pathComponents = resourceUrl.pathname.split('/');\n const specLiteral = pathComponents.pop();\n const pathName = pathComponents.pop();\n\n if (specLiteral !== 'spec') {\n throw new Error('invalid resource uri');\n }\n\n const pathSpec = openApiSpec.paths[`/${pathName}`];\n\n if (!pathSpec) {\n throw new Error('path not found');\n }\n\n return {\n contents: [\n {\n uri: request.params.uri,\n mimeType: 'application/json',\n text: JSON.stringify(pathSpec),\n },\n ],\n };\n });\n\n this.setRequestHandler(ListToolsRequestSchema, async () => {\n const tools = Object.entries(this.#tools).map(\n ([name, { description, parameters }]) => {\n return {\n name,\n description,\n inputSchema: zodToJsonSchema(parameters),\n };\n }\n );\n\n return {\n tools,\n };\n });\n\n this.setRequestHandler(CallToolRequestSchema, async (request) => {\n const tools = this.#tools;\n const toolName = request.params.name as keyof typeof tools;\n\n if (!(toolName in this.#tools)) {\n throw new Error('tool not found');\n }\n\n const tool = this.#tools[toolName];\n const args = tool.parameters.parse(request.params.arguments);\n\n if (!args) {\n throw new Error('missing arguments');\n }\n\n const result = await tool.execute(args as any);\n\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify(result),\n },\n ],\n };\n });\n }\n\n async #fetchOpenApiSpec() {\n const response = await fetch(ensureTrailingSlash(this.#apiUrl), {\n headers: this.#getHeaders(),\n });\n\n return (await response.json()) as any;\n }\n\n #getHeaders(method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' = 'GET') {\n const schemaHeader =\n method === 'GET' ? 'accept-profile' : 'content-profile';\n\n const headers: HeadersInit = {\n 'content-type': 'application/json',\n prefer: 'return=representation',\n [schemaHeader]: this.#schema,\n };\n\n if (this.#apiKey) {\n headers.apikey = this.#apiKey;\n headers.authorization = `Bearer ${this.#apiKey}`;\n }\n\n return headers;\n }\n}\n","{\n \"name\": \"@supabase/mcp-server-postgrest\",\n \"version\": \"0.1.0\",\n \"description\": \"MCP server for PostgREST\",\n \"license\": \"MIT\",\n \"type\": \"module\",\n \"main\": \"dist/index.cjs\",\n \"types\": \"dist/index.d.ts\",\n \"sideEffects\": false,\n \"scripts\": {\n \"build\": \"tsup --clean\",\n \"prepublishOnly\": \"npm run build\",\n \"test\": \"vitest\"\n },\n \"files\": [\n \"dist/**/*\"\n ],\n \"bin\": {\n \"mcp-server-postgrest\": \"./dist/stdio.js\"\n },\n \"exports\": {\n \".\": {\n \"import\": \"./dist/index.js\",\n \"types\": \"./dist/index.d.ts\",\n \"default\": \"./dist/index.cjs\"\n }\n },\n \"dependencies\": {\n \"@modelcontextprotocol/sdk\": \"^1.0.4\",\n \"@supabase/sql-to-rest\": \"^0.1.6\",\n \"zod\": \"^3.24.1\",\n \"zod-to-json-schema\": \"^3.24.1\"\n },\n \"devDependencies\": {\n \"@supabase/mcp-utils\": \"*\",\n \"@total-typescript/tsconfig\": \"^1.0.4\",\n \"@types/node\": \"^22.8.6\",\n \"prettier\": \"^3.3.3\",\n \"tsup\": \"^8.3.5\",\n \"tsx\": \"^4.19.2\",\n \"typescript\": \"^5.6.3\",\n \"vitest\": \"^2.1.4\"\n }\n}\n","/**\n * Ensures that a URL has a trailing slash.\n */\nexport function ensureTrailingSlash(url: string) {\n return url.endsWith('/') ? url : `${url}/`;\n}\n\n/**\n * Ensures that a URL does not have a trailing slash.\n */\nexport function ensureNoTrailingSlash(url: string) {\n return url.endsWith('/') ? url.slice(0, -1) : url;\n}\n"]}Report false positiveScan History
| Date | Risk | Findings | Files | Duration |
|---|---|---|---|---|
| Feb 25, 2026 | low | 14 | 19 | 0.00s |
| Feb 23, 2026 | low | 14 | 19 | 0.00s |
| Feb 22, 2026 | low | 14 | 19 | 0.00s |