Koskamo

Pugi MCP

An official MCP server for Pugi that allows AI agents to build, secure, and manage web applications. It provides tools for scanning URLs and repositories for security issues, checking account balance, purchasing credits, publishing status, searching the public catalog, and generating logos.

Endpoint and access

No sign-in to connect and list tools. Individual tools may still need a vendor account, credentials, or permissions; check the documented prerequisites.

Pugi MCP logo, by PugiVendor evidenceStreamable HTTPNo sign-inEndpoint checked 2026-11-01Operated by Pugi
You need:Agent API key: `POST https://api.pugi.io/api/agent/v1/keys` with no Authorization header creates an agent account and its first key
MCP endpoint (Streamable HTTP)
https://api.pugi.io/api/agent/v1/mcp
Vendor documentation

What you can do with it

  • Scan a public URL for security vulnerabilities
  • Search the Pugi catalog for app templates
  • Generate logos for a business name
  • Check account balance and purchase credits

Source and maintenance

Vendor evidenceRegistry 1.0.0

Protocol and capabilities

Server
pugi 1.0.0
MCP protocol
2025-06-18
Tools
14 advertised
Resources
10 advertised
Resource templates
0 advertised
Prompts
Not advertised
Server-advertised capabilities
{
  "tools": {
    "listChanged": false
  },
  "resources": {
    "subscribe": false,
    "listChanged": false
  },
  "extensions": {
    "io.modelcontextprotocol/ui": {
      "mimeTypes": [
        "text/html;profile=mcp-app"
      ]
    }
  }
}

Server-provided instructions

Untrusted server output shown for inspection. It is not Koskamo guidance and is excluded from knowledge search.

Pugi is an AI product team that builds, checks and publishes websites and apps. With this key you can check a public website for security issues (free), see your credit balance, make four whole logos for a business name (three free calls a day per key, then $0.25), get a card checkout link a person can open to add credit, see the status of apps you published, search the public catalogue of sites and apps to start from (free), and check a public GitHub repository for leaked secrets, vulnerable dependencies and risky code (3 free checks a day per account, then $1 when the check finishes). Where open, build a website from a brief (build_site), change it (edit), follow it and review it on a view-only preview (job_status, free) and put it live (publish, free); builds on a plan are included in the subscription. Do not quote build costs unless the user asks. For credit accounts, show the final charge at the end, not on every progress check. Credit builds are billed by actual cost, never above max_usd. App builds (build_app) work the same way; an app that needs a server or a database moves onto our servers on its own. Paid tools spend prepaid credit; no tool here takes a payment by itself. Prices: https://api.pugi.io/api/agent/v1/pricing An agent can also pay without a person. Agent payments are business purchases. Buyers in the EU and the UK need a valid VAT number; anyone else can pay as a person on our checkout page. Outside the EU and the UK no declaration is needed; EU and UK buyers declare the business with its VAT number once (POST https://api.pugi.io/api/agent/v1/business). Then a call without enough credit answers with a payment challenge (error -32042) that an agent wallet can pay by card (a Shared Payment Token, from $5 of credit) and retry. Your wallet decides and pays; Pugi never charges on its own.

Tools

14 advertised

get_balance — Get credit balance
Advertised by the server during the last successful anonymous check.
Advertised read-only

Use this when the person asks about their Pugi plan, credit or what they spent today. Free and read-only.

get_balance input schema
{
  "type": "object",
  "properties": {},
  "additionalProperties": false
}
get_balance annotations
{
  "title": "Get credit balance",
  "readOnlyHint": true,
  "openWorldHint": false,
  "idempotentHint": true,
  "destructiveHint": false
}
buy_credits_link — Get a link to add credit
Advertised by the server during the last successful anonymous check.
Advertised read-only

Get a link to add credit.

buy_credits_link input schema
{
  "type": "object",
  "properties": {
    "amount_usd": {
      "type": "number",
      "maximum": 100,
      "minimum": 1,
      "description": "How much credit to add. Rounded up to a pack of 5, 10, 25, 50 or 100 USD. Default 5."
    }
  },
  "additionalProperties": false
}
buy_credits_link annotations
{
  "title": "Get a link to add credit",
  "readOnlyHint": true,
  "openWorldHint": false,
  "idempotentHint": true,
  "destructiveHint": false
}
scan_url — Check a website for security issues
Advertised by the server during the last successful anonymous check.
Advertised read-onlyOpen-world

Use this when the person wants a public website checked for security problems, for example "is my site secure?" or "check example.com". Free and read-only: HTTPS, security headers, cookie flags and exposed keys, with a grade from A+ to F and how to fix each finding. Not a pentest. Do not use for private or local addresses or for code repositories (use scan_repo).

scan_url input schema
{
  "type": "object",
  "required": [
    "url"
  ],
  "properties": {
    "url": {
      "type": "string",
      "maxLength": 2048,
      "description": "The public address to check, for example https://example.com"
    },
    "language": {
      "type": "string",
      "pattern": "^[a-z]{2,3}(-[A-Za-z0-9]{2,8})?$",
      "maxLength": 35,
      "description": "The language the person is writing in, as a BCP 47 tag such as \"ru\"."
    }
  },
  "additionalProperties": false
}
scan_url annotations
{
  "title": "Check a website for security issues",
  "readOnlyHint": true,
  "openWorldHint": true,
  "idempotentHint": true,
  "destructiveHint": false
}
make_logo — Make four logos
Advertised by the server during the last successful anonymous check.
Advertised destructiveOpen-world

Use this when the person wants a logo or brand mark for a business, shop, product or project, for example "make a logo for Blue Fern Bakery". business_name must be the name the person gave, in their own words. If they gave no name, do not call this tool: ask them what the company is called, in their language (in Russian: «Как называется компания?»); never invent or translate a name. Pass their description and their own style words verbatim (never add style, colour or mood words yourself), and language (the language they write in). After a call, never describe what you passed to Pugi, name the tool or promise logos while a question is open; never say you passed something without calling. Pugi first asks the person to confirm the name in the card, once per name. If they say yes in words, call this tool again with the same business_name and the question_token. If they give another name in words, call this tool again with that business_name. A new business name is a new brand: never reuse another business's logo or answers. Pugi runs the same short brand interview as logo.pugi.io, one question per call (status needs_input), shown with its options in the card: tell the person in one short line to answer there or in their own words, without listing the options, then call again with their answer (trade for the first question, answers for the later ones). Use draw_now true only when the person says to draw now. Then it draws four whole logo options (PNG) the person can pick, change and use on a Pugi website. Generates logo design assets only. Do not use for photos, illustrations, posters, memes or editing an image the person uploaded; to change logos already shown in this conversation use refine_logo.

make_logo input schema
{
  "type": "object",
  "anyOf": [
    {
      "required": [
        "business_name"
      ]
    },
    {
      "required": [
        "name"
      ]
    }
  ],
  "required": [
    "idempotency_key"
  ],
  "properties": {
    "name": {
      "type": "string",
      "maxLength": 60
    },
    "niche": {
      "type": "string",
      "maxLength": 300
    },
    "style": {
      "type": "string",
      "maxLength": 400,
      "description": "Style words verbatim; styles also accepts a list."
    },
    "trade": {
      "type": "string",
      "maxLength": 300,
      "description": "Only after Pugi asked (status needs_input): the slug the user picked from the options, for example \"coffee-shop\", or their own words."
    },
    "styles": {
      "type": "array",
      "items": {
        "type": "string",
        "maxLength": 400
      },
      "maxItems": 20,
      "description": "The user’s style words verbatim."
    },
    "answers": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "id",
          "answer"
        ],
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^[a-z_-]{1,24}$"
          },
          "answer": {
            "type": "string",
            "maxLength": 240,
            "minLength": 1
          },
          "question": {
            "type": "string",
            "maxLength": 160
          }
        },
        "additionalProperties": false
      },
      "maxItems": 8,
      "description": "Only after Pugi asked (status needs_input): every answer so far to its interview questions, the id Pugi gave and the user's words verbatim."
    },
    "colours": {
      "oneOf": [
        {
          "type": "object",
          "required": [
            "primary"
          ],
          "properties": {
            "text": {
              "type": "string",
              "pattern": "^#[0-9a-fA-F]{6}$"
            },
            "primary": {
              "type": "string",
              "pattern": "^#[0-9a-fA-F]{6}$"
            },
            "secondary": {
              "type": "string",
              "pattern": "^#[0-9a-fA-F]{6}$"
            }
          },
          "additionalProperties": false
        },
        {
          "type": "array",
          "items": {
            "type": "string",
            "pattern": "^#[0-9a-fA-F]{6}$"
          },
          "maxItems": 3,
          "minItems": 1
        }
      ],
      "description": "Optional. Hex colours: {\"primary\": \"#1e3a8a\", \"secondary\": \"#f59e0b\", \"text\": \"#111827\"}, or a list of one to three of them in that order."
    },
    "palette": {
      "type": "string",
      "maxLength": 100
    },
    "refines": {
      "type": "array",
      "items": {
        "type": "string",
        "maxLength": 400
      },
      "maxItems": 20
    },
    "tagline": {
      "type": "string",
      "maxLength": 200
    },
    "draw_now": {
      "type": "boolean",
      "description": "True when the user wants the logos drawn now, without more questions."
    },
    "industry": {
      "type": "string",
      "maxLength": 300,
      "description": "Optional. What the business does, for example \"coffee shop\" or \"accounting firm\"."
    },
    "language": {
      "type": "string",
      "pattern": "^[a-z]{2,3}(-[A-Za-z0-9]{2,8})?$",
      "maxLength": 35,
      "description": "The language the user is writing to you in, as a BCP 47 tag such as \"uk\", \"de\" or \"pt-BR\"; the questions come back in it."
    },
    "name_proof": {
      "type": "string",
      "maxLength": 64,
      "description": "Set by Pugi's card when the person confirms the name. Leave it out."
    },
    "description": {
      "type": "string",
      "maxLength": 400,
      "description": "The user’s description verbatim, including location, imagery and mood."
    },
    "refine_notes": {
      "type": "string",
      "maxLength": 400
    },
    "business_name": {
      "type": "string",
      "maxLength": 60,
      "minLength": 1,
      "description": "The business name, as written by the user."
    },
    "question_token": {
      "type": "string",
      "maxLength": 64,
      "description": "Only after Pugi asked (status needs_input): the question_token it returned. Pass it with the trade, the answers or draw_now; without it the brief starts again."
    },
    "idempotency_key": {
      "type": "string",
      "pattern": "^[A-Za-z0-9._:-]{8,128}$",
      "maxLength": 128,
      "minLength": 8,
      "description": "A unique string for this call, reused only to retry it. The same key with the same arguments is never charged twice."
    }
  },
  "additionalProperties": false
}
make_logo annotations
{
  "title": "Make four logos",
  "readOnlyHint": false,
  "openWorldHint": true,
  "idempotentHint": true,
  "destructiveHint": true
}
publish_status — Get publish status
Advertised by the server during the last successful anonymous check.
Advertised read-only

Use this when the person asks which of their Pugi sites are live and at what address.

publish_status input schema
{
  "type": "object",
  "properties": {
    "language": {
      "type": "string",
      "pattern": "^[a-z]{2,3}(-[A-Za-z0-9]{2,8})?$",
      "maxLength": 35,
      "description": "The language the person is writing in, as a BCP 47 tag such as \"ru\"."
    },
    "project_id": {
      "type": "string",
      "maxLength": 200,
      "description": "Optional project id."
    }
  },
  "additionalProperties": false
}
publish_status annotations
{
  "title": "Get publish status",
  "readOnlyHint": true,
  "openWorldHint": false,
  "idempotentHint": true,
  "destructiveHint": false
}
catalog_search — Search the Pugi catalogue
Advertised by the server during the last successful anonymous check.
Advertised read-onlyOpen-world

Use this when the person wants ideas or a starting point for a site or app, for example "show me bakery websites". Free. Returns sites and apps people built with Pugi; if none matches it returns the nearest category and says so (match: nearest_category), so tell the person they are the nearest. Each has a brief and the tool to start a similar project in this chat (build_with). It does not copy anyone's code.

catalog_search input schema
{
  "type": "object",
  "properties": {
    "tags": {
      "type": "array",
      "items": {
        "type": "string",
        "maxLength": 24
      },
      "maxItems": 8,
      "description": "Optional tags; a card must carry every one, for example [\"saas\"]."
    },
    "limit": {
      "type": "integer",
      "maximum": 20,
      "minimum": 1,
      "description": "How many cards to return. Default 10."
    },
    "query": {
      "type": "string",
      "maxLength": 80,
      "description": "Optional words for what the person wants, in any language, for example \"booking\" or \"coffee shop\"."
    },
    "category": {
      "enum": [
        "portfolio",
        "landing_page",
        "blog",
        "editorial",
        "ecommerce",
        "events",
        "music",
        "resume",
        "services",
        "lifestyle",
        "saas",
        "dashboards",
        "internal_tools",
        "developer_tools",
        "business_tools",
        "productivity",
        "project_management",
        "product_management",
        "finance",
        "education",
        "real_estate",
        "food",
        "beauty_wellness",
        "fitness",
        "travel",
        "health",
        "nonprofit",
        "agency",
        "local_business",
        "other"
      ],
      "type": "string",
      "description": "Optional category."
    }
  },
  "additionalProperties": false
}
catalog_search annotations
{
  "title": "Search the Pugi catalogue",
  "readOnlyHint": true,
  "openWorldHint": true,
  "idempotentHint": true,
  "destructiveHint": false
}
scan_repo — Check a GitHub repository for security issues
Advertised by the server during the last successful anonymous check.
Advertised destructiveOpen-world

Use this when the person wants a public GitHub repository checked for leaked secrets, vulnerable or malicious dependencies and risky code. No code is run. 3 free checks a day per account, then $1 when the check finishes; a failed check costs nothing. Do not use for websites (use scan_url) or private repositories.

scan_repo input schema
{
  "type": "object",
  "required": [
    "repo_url",
    "idempotency_key"
  ],
  "properties": {
    "ref": {
      "type": "string",
      "maxLength": 240,
      "description": "Optional branch name. Default: the repository's default branch."
    },
    "language": {
      "type": "string",
      "pattern": "^[a-z]{2,3}(-[A-Za-z0-9]{2,8})?$",
      "maxLength": 35,
      "description": "The language the person is writing in, as a BCP 47 tag such as \"ru\"."
    },
    "repo_url": {
      "type": "string",
      "maxLength": 300,
      "description": "A public GitHub repository, for example https://github.com/owner/repo"
    },
    "idempotency_key": {
      "type": "string",
      "pattern": "^[A-Za-z0-9._:-]{8,128}$",
      "maxLength": 128,
      "minLength": 8,
      "description": "A unique string naming this check. Reuse it to collect the result or to retry; the same key is never charged twice."
    }
  },
  "additionalProperties": false
}
scan_repo annotations
{
  "title": "Check a GitHub repository for security issues",
  "readOnlyHint": false,
  "openWorldHint": true,
  "idempotentHint": true,
  "destructiveHint": true
}
build_app — Build a web app
Advertised by the server during the last successful anonymous check.
Advertised destructiveOpen-world

Use this when the person wants something people use: upload a photo, generate or transform pictures with AI, accounts or sign-in, saved data, a tool, a calculator, a game, bookings, a dashboard. Pass their request as they said it; never turn it into a landing page. An app that makes pictures with AI asks for the owner's own image-AI key; it never fakes results. Pass the customer's brief in the customer's own words; do not add features the customer did not ask for (no invented sign-up, accounts, subscriptions or payments). When it is built Pugi checks it for security issues, and publish waits for that check. An app that needs a server or a database moves onto Pugi's servers on its own; the person stays in this chat. In hosts that render the build card (MCP Apps or ChatGPT widget), the card tracks progress automatically: do not poll job_status. In hosts without a build card (Claude Code or API), call job_status with the job_id until the job is finished, stopped or failed. Do not use for a simple website (use build_site) or to change an app already built here (use edit).

build_app input schema
{
  "type": "object",
  "required": [
    "brief",
    "idempotency_key"
  ],
  "properties": {
    "pick": {
      "type": "string",
      "description": "Console gallery starter slug."
    },
    "brief": {
      "type": "string",
      "maxLength": 8000,
      "minLength": 10,
      "description": "The app to build, in the customer's own words."
    },
    "theme": {
      "type": "string",
      "description": "Console theme slug."
    },
    "locale": {
      "type": "string",
      "description": "Site language (legacy alias for site_language)."
    },
    "logo_id": {
      "type": "string",
      "description": "Selected logo_id returned by make_logo."
    },
    "max_usd": {
      "type": "number",
      "default": 5,
      "maximum": 25,
      "minimum": 1,
      "description": "The most this build may cost in USD (default 5)."
    },
    "language": {
      "type": "string",
      "pattern": "^[a-z]{2,3}(-[A-Za-z0-9]{2,8})?$",
      "maxLength": 35,
      "description": "The language the person is writing in, as a BCP 47 tag such as \"ru\"."
    },
    "without_logo": {
      "type": "boolean",
      "description": "True only when the person said this site should not use the logo they picked."
    },
    "brief_version": {
      "type": "string",
      "maxLength": 32,
      "description": "With brief_confirmed: the version of the summary the person agreed to, as returned with that summary."
    },
    "site_language": {
      "type": "string",
      "description": "Language for the app content; independent of the chat card language."
    },
    "brandHandoffId": {
      "type": "string",
      "description": "BrandHandoff from logo.pugi.io."
    },
    "brief_confirmed": {
      "type": "boolean",
      "description": "True only after the person has seen the summary and agreed. In a chat, without it nothing starts and the summary comes back."
    },
    "idempotency_key": {
      "type": "string",
      "pattern": "^[A-Za-z0-9._:-]{8,128}$",
      "maxLength": 128,
      "minLength": 8,
      "description": "A unique string naming this build. Reuse it only to retry the same call; it is never charged twice."
    }
  },
  "additionalProperties": false
}
build_app annotations
{
  "title": "Build a web app",
  "readOnlyHint": false,
  "openWorldHint": true,
  "idempotentHint": true,
  "destructiveHint": true
}
build_site — Build a website
Advertised by the server during the last successful anonymous check.
Advertised destructiveOpen-world

For a business's marketing site only, for example "a site for my bakery". Something people use (upload a photo, AI pictures, sign-in, a tool, a game) is an app: use build_app, never a landing page. Pass the customer's brief in the customer's own words; do not add features the customer did not ask for (no invented sign-up, accounts, subscriptions or payments). First call: nothing starts, a summary returns; after a yes, call with its action.arguments. In hosts that render the build card (MCP Apps or ChatGPT widget), the card tracks progress automatically: do not poll job_status. In hosts without a build card (Claude Code or API), call job_status with the job_id until the job is finished, stopped or failed. Not for changing a built site (use edit).

build_site input schema
{
  "type": "object",
  "required": [
    "brief",
    "idempotency_key"
  ],
  "properties": {
    "pick": {
      "type": "string",
      "description": "Console gallery starter slug."
    },
    "brief": {
      "type": "string",
      "maxLength": 8000,
      "minLength": 10,
      "description": "The customer's request in their own words: what the site is for and any pages, texts, colours or style they named. Do not add features they did not ask for."
    },
    "theme": {
      "type": "string",
      "description": "Console theme slug."
    },
    "locale": {
      "type": "string",
      "description": "Site language (legacy alias for site_language)."
    },
    "as_site": {
      "type": "boolean",
      "description": "True only when Pugi said this sounds like an app (app_suggested) and the person chose a marketing website anyway."
    },
    "logo_id": {
      "type": "string",
      "description": "Selected logo_id returned by make_logo."
    },
    "max_usd": {
      "type": "number",
      "maximum": 25,
      "minimum": 1,
      "description": "The run ceiling in USD; plan builds are included in the subscription. For credit builds, the most this build may cost. Default 5. Credit accounts pay actual cost, usually less."
    },
    "language": {
      "type": "string",
      "pattern": "^[a-z]{2,3}(-[A-Za-z0-9]{2,8})?$",
      "maxLength": 35,
      "description": "The language the person is writing in, as a BCP 47 tag such as \"ru\"."
    },
    "without_logo": {
      "type": "boolean",
      "description": "True only when the person said this site should not use the logo they picked."
    },
    "brief_version": {
      "type": "string",
      "maxLength": 32,
      "description": "With brief_confirmed: the version of the summary the person agreed to, as returned with that summary."
    },
    "site_language": {
      "type": "string",
      "description": "Language for the website content; independent of the chat card language."
    },
    "brandHandoffId": {
      "type": "string",
      "description": "BrandHandoff from logo.pugi.io."
    },
    "brief_confirmed": {
      "type": "boolean",
      "description": "True only after the person has seen the summary and agreed. In a chat, without it nothing starts and the summary comes back."
    },
    "idempotency_key": {
      "type": "string",
      "pattern": "^[A-Za-z0-9._:-]{8,128}$",
      "maxLength": 128,
      "minLength": 8,
      "description": "A unique string naming this job. The same key returns the same job and is never charged twice."
    }
  },
  "additionalProperties": false
}
build_site annotations
{
  "title": "Build a website",
  "readOnlyHint": false,
  "openWorldHint": true,
  "idempotentHint": true,
  "destructiveHint": true
}
edit — Change a site Pugi built
Advertised by the server during the last successful anonymous check.
Advertised destructiveOpen-world

Use this when the person asks to change a Pugi website or app from this conversation: "change the headline", "make the buttons green", "add a menu page". Pass the change in the customer's own words; do not add features the customer did not ask for (no invented sign-up, accounts, subscriptions or payments). Pass the job_id or project_id from the last build result. Do not use to start a new site or app. In hosts that render the build card (MCP Apps or ChatGPT widget), the card tracks progress automatically: do not poll job_status. In hosts without a build card (Claude Code or API), call job_status with the job_id until the job is finished, stopped or failed.

edit input schema
{
  "type": "object",
  "required": [
    "instruction",
    "idempotency_key"
  ],
  "properties": {
    "pick": {
      "type": "string",
      "description": "Console gallery starter slug."
    },
    "theme": {
      "type": "string",
      "description": "Console theme slug."
    },
    "job_id": {
      "type": "string",
      "description": "The job_id of the build (or of an earlier edit) of the site to change."
    },
    "locale": {
      "type": "string",
      "description": "Site language (legacy alias for site_language)."
    },
    "logo_id": {
      "type": "string",
      "description": "Selected logo_id returned by make_logo."
    },
    "max_usd": {
      "type": "number",
      "maximum": 25,
      "minimum": 0.5,
      "description": "The run ceiling in USD; plan edits are included in the subscription. For credit edits, the most this change may cost. Default 2."
    },
    "language": {
      "type": "string",
      "pattern": "^[a-z]{2,3}(-[A-Za-z0-9]{2,8})?$",
      "maxLength": 35,
      "description": "The language the person is writing in, as a BCP 47 tag such as \"ru\"."
    },
    "project_id": {
      "type": "string",
      "description": "Or the project_id of that site."
    },
    "instruction": {
      "type": "string",
      "maxLength": 8000,
      "minLength": 10,
      "description": "The change to make, in plain words."
    },
    "without_logo": {
      "type": "boolean",
      "description": "True only when the person said this site should not use the logo they picked."
    },
    "brief_version": {
      "type": "string",
      "maxLength": 32,
      "description": "With brief_confirmed: the version of the summary the person agreed to, as returned with that summary."
    },
    "site_language": {
      "type": "string",
      "description": "Language for the website content; independent of the chat card language."
    },
    "brandHandoffId": {
      "type": "string",
      "description": "BrandHandoff from logo.pugi.io."
    },
    "brief_confirmed": {
      "type": "boolean",
      "description": "True only after the person has seen the summary and agreed. In a chat, without it nothing starts and the summary comes back."
    },
    "idempotency_key": {
      "type": "string",
      "pattern": "^[A-Za-z0-9._:-]{8,128}$",
      "maxLength": 128,
      "minLength": 8,
      "description": "A unique string naming this job. The same key returns the same job and is never charged twice."
    }
  },
  "additionalProperties": false
}
edit annotations
{
  "title": "Change a site Pugi built",
  "readOnlyHint": false,
  "openWorldHint": true,
  "idempotentHint": true,
  "destructiveHint": true
}
job_status — Get the status of a build
Advertised by the server during the last successful anonymous check.

Use this when the person asks how a Pugi build or change is going, or for a fresh preview link. In hosts that render the build card (MCP Apps or ChatGPT widget), the card tracks progress automatically: do not poll job_status. In hosts without a build card (Claude Code or API), call job_status with the job_id until the job is finished, stopped or failed. Preview links expire after 15 minutes; call again for a fresh link.

job_status input schema
{
  "type": "object",
  "required": [
    "job_id"
  ],
  "properties": {
    "job_id": {
      "type": "string",
      "description": "The job_id build_site, build_app or edit returned."
    }
  },
  "additionalProperties": false
}
job_status annotations
{
  "title": "Get the status of a build",
  "readOnlyHint": false,
  "openWorldHint": false,
  "idempotentHint": true,
  "destructiveHint": false
}
publish — Publish a built site
Advertised by the server during the last successful anonymous check.
Advertised destructiveOpen-world

Use this when the person asks to put a Pugi website or app live ("publish", "go live"). Free. Puts the latest version on its pugi.app address after the security check every Pugi publish runs; publishing again replaces the live version.

publish input schema
{
  "type": "object",
  "properties": {
    "job_id": {
      "type": "string",
      "description": "The job_id of the build (or the latest edit) to publish."
    },
    "language": {
      "type": "string",
      "pattern": "^[a-z]{2,3}(-[A-Za-z0-9]{2,8})?$",
      "maxLength": 35,
      "description": "The language the person is writing in, as a BCP 47 tag such as \"ru\"."
    },
    "project_id": {
      "type": "string",
      "description": "Or the project_id of that site."
    },
    "idempotency_key": {
      "type": "string",
      "pattern": "^[A-Za-z0-9._:-]{8,128}$",
      "maxLength": 128,
      "minLength": 8,
      "description": "Optional. Reuse it to retry the same publish."
    },
    "publish_with_samples": {
      "type": "boolean",
      "description": "Only after the person saw the list of sample details this tool answered with (sample_facts_remain) and chose to keep them."
    }
  },
  "additionalProperties": false
}
publish annotations
{
  "title": "Publish a built site",
  "readOnlyHint": false,
  "openWorldHint": true,
  "idempotentHint": true,
  "destructiveHint": true
}
select_logo — Keep a logo
Advertised by the server during the last successful anonymous check.

Use this when the person picks one of the Pugi logos shown in this conversation (in the card or in words, such as "the second one"). Saves that logo for their business and returns the summary a website or app will be built from: show it and wait. Call again with correction when they change anything in the summary. Draws and buys nothing.

select_logo input schema
{
  "type": "object",
  "required": [
    "logo_id"
  ],
  "properties": {
    "logo_id": {
      "type": "string",
      "pattern": "^logo_[a-f0-9]{64}_[1-4]$",
      "description": "The logo_id of the picked logo, from the last logo result."
    },
    "language": {
      "type": "string",
      "maxLength": 20,
      "description": "The person's language."
    },
    "correction": {
      "type": "string",
      "maxLength": 600,
      "description": "The person's correction to the summary, in their own words."
    }
  },
  "additionalProperties": false
}
select_logo annotations
{
  "title": "Keep a logo",
  "readOnlyHint": false,
  "openWorldHint": false,
  "idempotentHint": true,
  "destructiveHint": false
}
refine_logo — Change the logos
Advertised by the server during the last successful anonymous check.
Advertised destructiveOpen-world

Use this when the person asks to change Pugi logos already shown in this conversation: other colours, a calmer or bolder mood, another icon or font, "like the second one but blue". Draws four new options from the same brief plus that change, without asking anything. Do not use for a different business name (use make_logo).

refine_logo input schema
{
  "type": "object",
  "required": [
    "logo_id",
    "change",
    "idempotency_key"
  ],
  "properties": {
    "change": {
      "type": "string",
      "maxLength": 400,
      "minLength": 1,
      "description": "The change in the person's own words, for example \"make it blue and calmer\"."
    },
    "logo_id": {
      "type": "string",
      "pattern": "^logo_[a-f0-9]{64}_[1-4]$",
      "description": "The logo_id of one of the logos to change, from the last logo result (the picked one when there is one)."
    },
    "language": {
      "type": "string",
      "pattern": "^[a-z]{2,3}(-[A-Za-z0-9]{2,8})?$",
      "maxLength": 35,
      "description": "The language the person writes in, as a BCP 47 tag such as \"ru\"."
    },
    "idempotency_key": {
      "type": "string",
      "pattern": "^[A-Za-z0-9._:-]{8,128}$",
      "maxLength": 128,
      "minLength": 8,
      "description": "A unique string for this call, reused only to retry it."
    }
  },
  "additionalProperties": false
}
refine_logo annotations
{
  "title": "Change the logos",
  "readOnlyHint": false,
  "openWorldHint": true,
  "idempotentHint": true,
  "destructiveHint": true
}

Prompts

Not advertised

No prompt definitions available.

Resources

10 advertised

Pugi logos

Advertised by the server during the last successful anonymous check.

Pugi logos URI
ui://pugi/logos.c0f018f749a3.html

MIME type: text/html;profile=mcp-app

Pugi logos (ChatGPT compatibility)

Advertised by the server during the last successful anonymous check.

Pugi logos (ChatGPT compatibility) URI
ui://pugi/logos.c0f018f749a3.skybridge.html

MIME type: text/html+skybridge

Pugi build

Advertised by the server during the last successful anonymous check.

Pugi build URI
ui://pugi/build.476a165c7ba7.html

MIME type: text/html;profile=mcp-app

Pugi build (ChatGPT compatibility)

Advertised by the server during the last successful anonymous check.

Pugi build (ChatGPT compatibility) URI
ui://pugi/build.476a165c7ba7.skybridge.html

MIME type: text/html+skybridge

Pugi website

Advertised by the server during the last successful anonymous check.

Pugi website URI
ui://pugi/website.5a3dab5d3f13.html

MIME type: text/html;profile=mcp-app

Pugi website (ChatGPT compatibility)

Advertised by the server during the last successful anonymous check.

Pugi website (ChatGPT compatibility) URI
ui://pugi/website.5a3dab5d3f13.skybridge.html

MIME type: text/html+skybridge

Pugi repository

Advertised by the server during the last successful anonymous check.

Pugi repository URI
ui://pugi/repository.757d65698a02.html

MIME type: text/html;profile=mcp-app

Pugi repository (ChatGPT compatibility)

Advertised by the server during the last successful anonymous check.

Pugi repository (ChatGPT compatibility) URI
ui://pugi/repository.757d65698a02.skybridge.html

MIME type: text/html+skybridge

Pugi published

Advertised by the server during the last successful anonymous check.

Pugi published URI
ui://pugi/published.9b99cd9db51b.html

MIME type: text/html;profile=mcp-app

Pugi published (ChatGPT compatibility)

Advertised by the server during the last successful anonymous check.

Pugi published (ChatGPT compatibility) URI
ui://pugi/published.9b99cd9db51b.skybridge.html

MIME type: text/html+skybridge

30-day availability

Aggregated from read-only remote checks; this is not a tool-execution or security guarantee.

Successful checks
1 of 1 (100%)
Average latency
1251 ms
95th percentile latency
1251 ms

Maintenance history

Public check and source-refresh events. Editorial and ownership records remain private.

  • · probe · passed · 1251 ms · metadata changed · 14 tool(s), 10 resource(s), 0 resource template(s)

Connect from your client

Each snippet registers the same endpoint; pick the client you use.

This server is operated by the named third party. Listing and endpoint checks are not an endorsement or a security audit. Review the operator's permissions, terms, and data handling before connecting. How listings are checked and corrected.

Claude Code

Run this once in a terminal. It registers the remote server. Use --scope project to write .mcp.json for the repo.
Claude Code configuration
claude mcp add --transport http pugi-mcp https://api.pugi.io/api/agent/v1/mcp

Codex

Run this once. Codex stores MCP servers in ~/.codex/config.toml (or .codex/config.toml in a trusted project).
Codex configuration
codex mcp add pugi-mcp --url https://api.pugi.io/api/agent/v1/mcp

Cursor

Merge this server into .cursor/mcp.json in your project, then enable pugi-mcp in your MCP settings.
Cursor configuration
{
  "mcpServers": {
    "pugi-mcp": {
      "url": "https://api.pugi.io/api/agent/v1/mcp"
    }
  }
}

Cline

Merge this into cline_mcp_settings.json (Cline → MCP Servers → Configure).
Cline configuration
{
  "mcpServers": {
    "pugi-mcp": {
      "type": "streamableHttp",
      "url": "https://api.pugi.io/api/agent/v1/mcp",
      "disabled": false
    }
  }
}

VS Code

Merge this server into .vscode/mcp.json. Use MCP: List Servers to start pugi-mcp and inspect its tools.
VS Code configuration
{
  "servers": {
    "pugi-mcp": {
      "type": "http",
      "url": "https://api.pugi.io/api/agent/v1/mcp"
    }
  }
}

Gemini CLI

Run this once. It writes .gemini/settings.json in the current project; pass --scope user for ~/.gemini/settings.json.
Gemini CLI configuration
gemini mcp add --transport http pugi-mcp https://api.pugi.io/api/agent/v1/mcp

Claude Desktop

Merge this into claude_desktop_config.json (macOS: ~/Library/Application Support/Claude/, Windows: %APPDATA%\Claude\), then restart Claude Desktop.
Claude Desktop configuration
{
  "mcpServers": {
    "pugi-mcp": {
      "url": "https://api.pugi.io/api/agent/v1/mcp"
    }
  }
}

Windsurf

Merge this into ~/.codeium/windsurf/mcp_config.json, then refresh MCP in Cascade. Windsurf remote servers use serverUrl, not url.
Windsurf configuration
{
  "mcpServers": {
    "pugi-mcp": {
      "serverUrl": "https://api.pugi.io/api/agent/v1/mcp"
    }
  }
}

Let your agent find its tools

Find servers like Pugi MCP from your agent. Add Koskamo once to search the index for endpoints, access requirements, and client setup. Public discovery needs no key.

Do you run Pugi MCP?

Prove ownership with a DNS record, a well-known file, or your Official MCP Registry entry, and your edits publish immediately. Proofs are re-checked weekly; admins can still hide or remove a listing.

Claim this listing