New:Socket for Asana Is Now Available.Learn more
Get Started

@wcagc/mcp

Package Overview
Dependencies
Maintainers
1
Versions
17
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@wcagc/mcp - npm Package Compare versions

Comparing version
0.7.0
to
0.7.1
+8
dist/tool-metadata.js
/**
* ChatGPT needs each tool to describe its own auth policy before it can surface the OAuth
* account-linking flow. The current MCP TypeScript SDK carries this Apps SDK extension through
* descriptor `_meta`; keep the value shared so all tools advertise the same hosted scope.
*/
export const OAUTH_TOOL_META = {
securitySchemes: [{ type: "oauth2", scopes: ["mcp:scan"] }],
};
+3
-0

@@ -41,2 +41,5 @@ function num(envVar, fallback) {

mcpServerUrl,
// OpenAI supplies this token during Plugins Directory domain verification. It stays in the
// deployment secret store; the hosted server exposes it verbatim only on the well-known path.
openAiAppsChallenge: process.env.WCAGC_OPENAI_APPS_CHALLENGE,
jwksCacheTtlSeconds: num(process.env.WCAGC_MCP_JWKS_TTL_SECONDS, 300),

@@ -43,0 +46,0 @@ // ── check_pdf url fetch (wcagc-api only accepts multipart bytes — see src/pdf-fetch.ts) ──

@@ -32,2 +32,9 @@ import { requireBearerAuth } from "@modelcontextprotocol/sdk/server/auth/middleware/bearerAuth.js";

});
app.get("/.well-known/openai-apps-challenge", (_req, res) => {
if (!config.openAiAppsChallenge) {
res.sendStatus(404);
return;
}
res.status(200).type("text/plain").send(config.openAiAppsChallenge);
});
const issuer = config.oauthIssuer.replace(/\/+$/, "");

@@ -34,0 +41,0 @@ const oauthMetadata = {

+1
-1

@@ -9,3 +9,3 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";

// test/version.test.ts fails the build if the two ever drift.
export const VERSION = "0.7.0";
export const VERSION = "0.7.1";
/**

@@ -12,0 +12,0 @@ * One server, two transports (hosted Streamable HTTP + local stdio) share this — the tool

@@ -5,2 +5,3 @@ import { z } from "zod";

import { fetchPdf, PdfFetchError } from "../pdf-fetch.js";
import { OAUTH_TOOL_META } from "../tool-metadata.js";
import { toolError } from "../tool-error.js";

@@ -50,2 +51,3 @@ import { disclaimerShape, withDisclaimer } from "./common.js";

outputSchema: pdfCheckOutputShape,
_meta: OAUTH_TOOL_META,
annotations: {

@@ -57,3 +59,3 @@ title: "Check a PDF for PDF/UA-1 conformance",

idempotentHint: false,
openWorldHint: true,
openWorldHint: false,
},

@@ -92,2 +94,3 @@ }, async ({ url }, extra) => {

outputSchema: pdfCheckOutputShape,
_meta: OAUTH_TOOL_META,
annotations: {

@@ -94,0 +97,0 @@ title: "Get a PDF check by id",

@@ -5,2 +5,3 @@ import { z } from "zod";

import { COVERAGE_DISCLAIMER } from "../disclaimer.js";
import { OAUTH_TOOL_META } from "../tool-metadata.js";
import { toolError } from "../tool-error.js";

@@ -152,10 +153,20 @@ import { disclaimerShape, failureReasonSchema, severityCountsSchema, summarizeScanLike, withDisclaimer, } from "./common.js";

/**
* Queues real work that drives a browser against pages out on the internet, and spends quota
* doing it. Nothing is ever deleted or overwritten — a scan only appends — so destructive stays
* false, but the world it reaches into is open and the outcome is not repeatable.
* Queues private WCAGC work and spends quota. Nothing is deleted or overwritten and the tools do
* not publish or mutate public internet state, so both destructive and open-world stay false.
*/
const QUEUES_WORK = {
const QUEUES_PRIVATE_WORK = {
readOnlyHint: false,
destructiveHint: false,
idempotentHint: false,
openWorldHint: false,
};
/**
* A saved journey can contain clicks or fills that submit a form or trigger another external,
* irreversible action. It therefore needs both warnings even though the steps are configured in
* WCAGC rather than accepted as raw arguments to this tool.
*/
const RUNS_EXTERNAL_JOURNEY = {
readOnlyHint: false,
destructiveHint: true,
idempotentHint: false,
openWorldHint: true,

@@ -179,2 +190,3 @@ };

outputSchema: { sites: z.array(siteSchema) },
_meta: OAUTH_TOOL_META,
annotations: { title: "List registered sites", ...READ_ONLY },

@@ -203,3 +215,4 @@ }, async (_args, extra) => {

outputSchema: { run: runSchema, ...disclaimerShape },
annotations: { title: "Start a full-site scan", ...QUEUES_WORK },
_meta: OAUTH_TOOL_META,
annotations: { title: "Start a full-site scan", ...QUEUES_PRIVATE_WORK },
}, async ({ siteHost }, extra) => {

@@ -231,2 +244,3 @@ try {

outputSchema: { run: runSchema, ...disclaimerShape },
_meta: OAUTH_TOOL_META,
annotations: { title: "Get a full-site scan run by id", ...READ_ONLY },

@@ -254,2 +268,3 @@ }, async ({ runId }, extra) => {

outputSchema: { violations: z.array(runViolationSchema) },
_meta: OAUTH_TOOL_META,
annotations: { title: "Get a full-site scan run's findings", ...READ_ONLY },

@@ -279,2 +294,3 @@ }, async ({ runId }, extra) => {

outputSchema: { rootCauses: rootCausesSchema },
_meta: OAUTH_TOOL_META,
annotations: { title: "Get a scan run's root causes", ...READ_ONLY },

@@ -304,4 +320,5 @@ }, async ({ runId }, extra) => {

"AUTHENTICATED_SCANS when the journey logs in). Steps and any login credential always come " +
"from the journey's own saved configuration — never accepted here. Queues the run and " +
"returns immediately with a runId — call get_journey_run to poll.",
"from the journey's own saved configuration — never accepted here. Saved click or fill " +
"steps can submit forms or trigger external actions, so run only a journey the user has " +
"reviewed. Queues the run and returns immediately with a runId — call get_journey_run to poll.",
inputSchema: {

@@ -312,3 +329,4 @@ siteHost: z.string().describe("The registered site's normalized host, as list_sites reports it."),

outputSchema: { run: journeyRunSchema, ...disclaimerShape },
annotations: { title: "Run a saved user journey", ...QUEUES_WORK },
_meta: OAUTH_TOOL_META,
annotations: { title: "Run a saved user journey", ...RUNS_EXTERNAL_JOURNEY },
}, async ({ siteHost, journeyName }, extra) => {

@@ -339,2 +357,3 @@ try {

outputSchema: { run: journeyRunSchema, ...disclaimerShape },
_meta: OAUTH_TOOL_META,
annotations: { title: "Get a journey run by id", ...READ_ONLY },

@@ -364,2 +383,3 @@ }, async ({ runId }, extra) => {

outputSchema: { trend: trendSchema, ...disclaimerShape },
_meta: OAUTH_TOOL_META,
annotations: { title: "Get a site's violation-count trend", ...READ_ONLY },

@@ -391,2 +411,3 @@ }, async ({ siteHost, limit }, extra) => {

outputSchema: { fixes: z.array(fixSchema), ...disclaimerShape },
_meta: OAUTH_TOOL_META,
annotations: { title: "List tracked fixes", ...READ_ONLY },

@@ -415,3 +436,4 @@ }, async ({ siteHost }, extra) => {

outputSchema: { verification: fixVerificationAcceptedSchema, pollWith: z.literal("get_fix_verification"), ...disclaimerShape },
annotations: { title: "Verify a tracked fix", ...QUEUES_WORK },
_meta: OAUTH_TOOL_META,
annotations: { title: "Verify a tracked fix", ...QUEUES_PRIVATE_WORK },
}, async ({ remediationItemId }, extra) => {

@@ -438,2 +460,3 @@ try {

outputSchema: { verification: fixVerificationSchema, ...disclaimerShape },
_meta: OAUTH_TOOL_META,
annotations: { title: "Get fix verification", ...READ_ONLY },

@@ -440,0 +463,0 @@ }, async ({ fixVerificationId }, extra) => {

import { z } from "zod";
import { McpApiError, apiJson } from "../api-client.js";
import { resolveBearer } from "../bearer.js";
import { OAUTH_TOOL_META } from "../tool-metadata.js";
import { toolError } from "../tool-error.js";

@@ -77,2 +78,3 @@ import { disclaimerShape, failureReasonSchema, severityCountsSchema, summarizeScanLike, withDisclaimer, } from "./common.js";

outputSchema: scanOutputShape,
_meta: OAUTH_TOOL_META,
annotations: {

@@ -85,3 +87,3 @@ title: "Scan a URL",

idempotentHint: false,
openWorldHint: true,
openWorldHint: false,
},

@@ -148,2 +150,3 @@ }, async ({ url }, extra) => {

outputSchema: scanOutputShape,
_meta: OAUTH_TOOL_META,
annotations: {

@@ -188,2 +191,3 @@ title: "Get a scan by id",

outputSchema: findingsOutputShape,
_meta: OAUTH_TOOL_META,
annotations: {

@@ -190,0 +194,0 @@ title: "Get a scan's findings",

{
"name": "@wcagc/mcp",
"version": "0.7.0",
"version": "0.7.1",
"mcpName": "io.github.WCAG-Compliance/mcp",

@@ -5,0 +5,0 @@ "description": "wcagc MCP server \u2014 a thin, stateless adapter that translates MCP tool calls into wcagc-api HTTP calls. No database, no secrets beyond WCAGC_API_BASE_URL (+ WCAGC_MCP_KEY for local stdio mode). Open-source: this package holds no business logic or credentials of its own.",

@@ -89,6 +89,7 @@ # wcagc-mcp

| `WCAGC_MCP_INTROSPECT_TTL_SECONDS` | hosted | How long a verified bearer is cached before re-checking with the API (default `60`). |
| `WCAGC_OAUTH_ISSUER` | hosted | Expected OAuth issuer. |
| `WCAGC_OAUTH_JWKS_URL` | hosted | Authorization Server public JWKS URL. |
| `WCAGC_MCP_SERVER_URL` | hosted | Canonical RFC 9728 protected-resource URL. |
| `WCAGC_OAUTH_JWKS_TTL_SECONDS` | hosted | JWKS cache TTL; an unknown `kid` triggers an immediate refetch. |
| `WCAGC_MCP_OAUTH_ISSUER` | hosted | Expected OAuth issuer (defaults to `WCAGC_API_BASE_URL`). |
| `WCAGC_MCP_OAUTH_JWKS_URL` | hosted | Authorization Server public JWKS URL. |
| `WCAGC_MCP_URL` | hosted | Canonical RFC 9728 protected-resource URL (defaults to `https://mcp.wcagc.com/mcp`). |
| `WCAGC_MCP_JWKS_TTL_SECONDS` | hosted | JWKS cache TTL; an unknown `kid` triggers an immediate refetch. |
| `WCAGC_OPENAI_APPS_CHALLENGE` | hosted | OpenAI Plugins Directory domain-verification token; keep it in the deployment secret store, never in source. |

@@ -95,0 +96,0 @@ ## Development