Skip to main content
Glama

Submit an AI or MCP tool to the Tulimoa directory

submit_listing

Create a new listing in the Tulimoa directory (AI and MCP software with its own website) on behalf of the authenticated user. It starts as 'pending' and is reviewed by hand. Required: logo_url (a public image URL, e.g. the company's square icon) and ai_usage (how the software uses AI or what agents can do with it). Choose how it goes live with visibility: 'badge' (free, Tulimoa badge on the website, reviewed within 7 days) or 'launch' ($5 one-time, no badge, reviewed first, refunded if rejected). For 'launch' ask the user for consent and pass withdrawal_consent: true; the result has a checkout_url the user opens to pay. For 'badge' the result has the badge HTML to embed. A website that is already listed cannot be submitted again. Use list_categories first to pick a valid category id. Requires a write-scoped Tulimoa login.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
mcpYestrue = this tool exposes its own MCP server.
urlYesPublic homepage URL (https).
nameYesProduct/company name (max 60 chars).
tagsNoOptional descriptive tags (max 8).
countryYesISO-3166-1 alpha-2 country code of the company, e.g. DE.
ai_usageYesRequired, 40 to 600 characters, ideally in English: how the software uses AI, or what agents can do with it. Be concrete, not salesy. Submissions without a clear AI or agent angle are rejected.
categoryYesOne category id. Call list_categories for valid ids.
gdpr_dpaNoOptional: a GDPR data processing agreement (DPA) is available.
logo_urlYesRequired. Public https URL of the company logo: PNG, JPEG, WebP, GIF or AVIF, at least 64 px, max 5 MB. A square icon works best. Tulimoa downloads it, scales it to max 512 px and stores it as WebP.
mcp_authNoOnly if mcp is true: how agents connect (oauth, api). Empty = no auth.
x_handleNoOptional company X handle, e.g. @acme.
visibilityYesHow the listing goes live (required). 'badge' = free: embed the Tulimoa badge on the product website, reviewed within 7 days; if the badge is missing for 14 days the listing goes offline again. 'launch' = $5 one-time launch package: no badge needed, reviewed first, optional welcome post from @gettulimoa on X, refunded automatically if rejected. Ask the user which one they want.
data_regionNoOptional. Where customer data is hosted: eu (in the EU by default), eu-option (an EU region can be selected), non-eu, self-hosted (runs at the customer). Listings with EU hosting also appear on tulimoa.com/mcp-eu.
launch_hookNoLaunch package with welcome post: one sentence why the tool matters (max 140 chars, English).
mcp_docs_urlNoOnly if mcp is true: link to the MCP docs.
model_sourceNoOptional: which AI models (own, open-weight, provider, mixed, none).
pricing_modelYesPricing model (required): free | freemium | paid | lifetime.
x_post_opt_inNoLaunch package only: a free welcome post from @gettulimoa on X after approval. Needs launch_hook and at least one X handle.
certificationsNoOptional: soc2, iso27001, hipaa.
mcp_server_urlNoOnly if mcp is true: endpoint URL of the MCP server.
pricing_detailNoOptional price detail, e.g. 'from $10/month'.
agent_interfacesNoOptional: other ways agents can use it.
hosting_providerNoOptional hosting provider and location, e.g. 'Hetzner, Falkenstein'.
founder_x_handlesNoOptional founder X handles (max 4).
short_descriptionYesOne-line pitch (max 300 chars).
withdrawal_consentNoRequired (true) for visibility 'launch'. Only set it after the user agrees: Tulimoa starts the review right away, the right of withdrawal ends once the listing is live, and a rejected listing gets the $5 back automatically.
trains_on_customer_dataNoOptional: trains on customer data (no, opt-out, yes).

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
idYesListing id.
slugYesFinal slug (may carry a conflict suffix).
statusYes
next_stepYesWhat the user has to do now.
badge_htmlNoBadge only: HTML for dark backgrounds (light) or light backgrounds (dark).
manage_urlYesDashboard page for status, badge check and payment.
visibilityYes
checkout_urlNoLaunch package only: opens the Polar checkout (Tulimoa login needed).

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed25 schema fields changed
    • addedInput schema / properties / agent_interfaces
      Added value: +{
      +  "description": "Optional: other ways agents can use it.",
      +  "items": {
      +    "enum": [
      +      "api",
      +      "cli",
      +      "sdk",
      +      "webhooks"
      +    ],
      +    "type": "string"
      +  },
      +  "maxItems": 4,
      +  "type": "array"
      +}
    • addedInput schema / properties / ai_usage
      Added value: +{
      +  "description": "Required, 40 to 600 characters, ideally in English: how the software uses AI, or what agents can do with it. Be concrete, not salesy. Submissions without a clear AI or agent angle are rejected.",
      +  "maxLength": 600,
      +  "minLength": 40,
      +  "type": "string"
      +}
    • addedInput schema / properties / certifications
      Added value: +{
      +  "description": "Optional: soc2, iso27001, hipaa.",
      +  "items": {
      +    "enum": [
      +      "soc2",
      +      "iso27001",
      +      "hipaa"
      +    ],
      +    "type": "string"
      +  },
      +  "maxItems": 3,
      +  "type": "array"
      +}
    • addedInput schema / properties / data_region
      Added value: +{
      +  "description": "Optional. Where customer data is hosted: eu (in the EU by default), eu-option (an EU region can be selected), non-eu, self-hosted (runs at the customer). Listings with EU hosting also appear on tulimoa.com/mcp-eu.",
      +  "enum": [
      +    "eu",
      +    "eu-option",
      +    "non-eu",
      +    "self-hosted"
      +  ],
      +  "type": "string"
      +}
    • addedInput schema / properties / founder_x_handles
      Added value: +{
      +  "description": "Optional founder X handles (max 4).",
      +  "items": {
      +    "maxLength": 40,
      +    "type": "string"
      +  },
      +  "maxItems": 4,
      +  "type": "array"
      +}
    • addedInput schema / properties / gdpr_dpa
      Added value: +{
      +  "description": "Optional: a GDPR data processing agreement (DPA) is available.",
      +  "type": "boolean"
      +}
    • addedInput schema / properties / hosting_provider
      Added value: +{
      +  "description": "Optional hosting provider and location, e.g. 'Hetzner, Falkenstein'.",
      +  "maxLength": 60,
      +  "type": "string"
      +}
    • addedInput schema / properties / launch_hook
      Added value: +{
      +  "description": "Launch package with welcome post: one sentence why the tool matters (max 140 chars, English).",
      +  "maxLength": 140,
      +  "type": "string"
      +}
    • addedInput schema / properties / mcp_auth
      Added value: +{
      +  "description": "Only if mcp is true: how agents connect (oauth, api). Empty = no auth.",
      +  "items": {
      +    "enum": [
      +      "oauth",
      +      "api"
      +    ],
      +    "type": "string"
      +  },
      +  "maxItems": 2,
      +  "type": "array"
      +}
    • addedInput schema / properties / mcp_docs_url
      Added value: +{
      +  "description": "Only if mcp is true: link to the MCP docs.",
      +  "format": "uri",
      +  "type": "string"
      +}
    • addedInput schema / properties / mcp_server_url
      Added value: +{
      +  "description": "Only if mcp is true: endpoint URL of the MCP server.",
      +  "format": "uri",
      +  "type": "string"
      +}
    • addedInput schema / properties / model_source
      Added value: +{
      +  "description": "Optional: which AI models (own, open-weight, provider, mixed, none).",
      +  "enum": [
      +    "own",
      +    "open-weight",
      +    "provider",
      +    "mixed",
      +    "none"
      +  ],
      +  "type": "string"
      +}
    • addedInput schema / properties / pricing_detail
      Added value: +{
      +  "description": "Optional price detail, e.g. 'from $10/month'.",
      +  "maxLength": 400,
      +  "type": "string"
      +}
    • addedInput schema / properties / trains_on_customer_data
      Added value: +{
      +  "description": "Optional: trains on customer data (no, opt-out, yes).",
      +  "enum": [
      +    "no",
      +    "opt-out",
      +    "yes"
      +  ],
      +  "type": "string"
      +}
    • addedInput schema / properties / visibility
      Added value: +{
      +  "description": "How the listing goes live (required). 'badge' = free: embed the Tulimoa badge on the product website, reviewed within 7 days; if the badge is missing for 14 days the listing goes offline again. 'launch' = $5 one-time launch package: no badge needed, reviewed first, optional welcome post from @gettulimoa on X, refunded automatically if rejected. Ask the user which one they want.",
      +  "enum": [
      +    "badge",
      +    "launch"
      +  ],
      +  "type": "string"
      +}
    • addedInput schema / properties / withdrawal_consent
      Added value: +{
      +  "description": "Required (true) for visibility 'launch'. Only set it after the user agrees: Tulimoa starts the review right away, the right of withdrawal ends once the listing is live, and a rejected listing gets the $5 back automatically.",
      +  "type": "boolean"
      +}
    • addedInput schema / properties / x_handle
      Added value: +{
      +  "description": "Optional company X handle, e.g. @acme.",
      +  "maxLength": 40,
      +  "type": "string"
      +}
    • addedInput schema / properties / x_post_opt_in
      Added value: +{
      +  "description": "Launch package only: a free welcome post from @gettulimoa on X after approval. Needs launch_hook and at least one X handle.",
      +  "type": "boolean"
      +}
    • changedInput schema / required
      Previous value: -[
      -  "name",
      -  "url",
      -  "short_description",
      -  "country",
      -  "category",
      -  "mcp",
      -  "pricing_model",
      -  "logo_url"
      -]New value: +[
      +  "name",
      +  "url",
      +  "short_description",
      +  "country",
      +  "category",
      +  "mcp",
      +  "pricing_model",
      +  "logo_url",
      +  "ai_usage",
      +  "visibility"
      +]
    • addedOutput schema / properties / badge_html
      Added value: +{
      +  "additionalProperties": false,
      +  "description": "Badge only: HTML for dark backgrounds (light) or light backgrounds (dark).",
      +  "properties": {
      +    "dark": {
      +      "type": "string"
      +    },
      +    "light": {
      +      "type": "string"
      +    }
      +  },
      +  "required": [
      +    "light",
      +    "dark"
      +  ],
      +  "type": "object"
      +}
    • addedOutput schema / properties / checkout_url
      Added value: +{
      +  "description": "Launch package only: opens the Polar checkout (Tulimoa login needed).",
      +  "type": "string"
      +}
    • addedOutput schema / properties / manage_url
      Added value: +{
      +  "description": "Dashboard page for status, badge check and payment.",
      +  "type": "string"
      +}
    • addedOutput schema / properties / next_step
      Added value: +{
      +  "description": "What the user has to do now.",
      +  "type": "string"
      +}
    • addedOutput schema / properties / visibility
      Added value: +{
      +  "enum": [
      +    "badge",
      +    "launch"
      +  ],
      +  "type": "string"
      +}
    • changedOutput schema / required
      Previous value: -[
      -  "id",
      -  "slug",
      -  "status"
      -]New value: +[
      +  "id",
      +  "slug",
      +  "status",
      +  "visibility",
      +  "next_step",
      +  "manage_url"
      +]
  2. Changed2 schema fields changed
    • addedInput schema / properties / logo_url
      Added value: +{
      +  "description": "Required. Public https URL of the company logo: PNG, JPEG, WebP, GIF or AVIF, at least 64 px, max 5 MB. A square icon works best. Tulimoa downloads it, scales it to max 512 px and stores it as WebP.",
      +  "format": "uri",
      +  "type": "string"
      +}
    • changedInput schema / required
      Previous value: -[
      -  "name",
      -  "url",
      -  "short_description",
      -  "country",
      -  "category",
      -  "mcp",
      -  "pricing_model"
      -]New value: +[
      +  "name",
      +  "url",
      +  "short_description",
      +  "country",
      +  "category",
      +  "mcp",
      +  "pricing_model",
      +  "logo_url"
      +]
  3. Changed2 schema fields changed
    • changedInput schema / $schema
      Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
    • changedOutput schema / (root)
      Previous value: -nullNew value: +{
      +  "$schema": "https://json-schema.org/draft/2020-12/schema",
      +  "additionalProperties": false,
      +  "properties": {
      +    "id": {
      +      "description": "Listing id.",
      +      "type": "string"
      +    },
      +    "slug": {
      +      "description": "Final slug (may carry a conflict suffix).",
      +      "type": "string"
      +    },
      +    "status": {
      +      "const": "pending",
      +      "type": "string"
      +    }
      +  },
      +  "required": [
      +    "id",
      +    "slug",
      +    "status"
      +  ],
      +  "type": "object"
      +}
  4. Changed3 schema fields changed
    • changedInput schema / properties / category / enum
      Previous value: -[
      -  "sales-crm",
      -  "marketing",
      -  "communication",
      -  "productivity",
      -  "developer-tools",
      -  "finance-ops",
      -  "hr-people",
      -  "customer-support",
      -  "data-analytics",
      -  "ai-infra",
      -  "compliance-hosting"
      -]New value: +[
      +  "developer-tools",
      +  "ai-infra",
      +  "sales-crm",
      +  "marketing",
      +  "productivity",
      +  "data-analytics",
      +  "finance-accounting",
      +  "customer-support",
      +  "hr-recruiting",
      +  "design-creative",
      +  "security-privacy",
      +  "communication",
      +  "commerce-payments",
      +  "automation-nocode",
      +  "other"
      +]
    • changedInput schema / properties / pricing_model / description
      Previous value: -"Optional: free | freemium | paid | lifetime."New value: +"Pricing model (required): free | freemium | paid | lifetime."
    • changedInput schema / required
      Previous value: -[
      -  "name",
      -  "url",
      -  "short_description",
      -  "country",
      -  "category",
      -  "mcp"
      -]New value: +[
      +  "name",
      +  "url",
      +  "short_description",
      +  "country",
      +  "category",
      +  "mcp",
      +  "pricing_model"
      +]
  5. Added

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden and delivers: the listing starts as 'pending' and is reviewed by hand, badge listings go offline if the badge is missing for 14 days, launch listings are reviewed first and auto-refunded if rejected, and withdrawal consent must be obtained before setting withdrawal_consent. It also previews the outputs (checkout_url for launch, badge HTML for badge), which is genuinely useful even alongside an output schema.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Purpose, required fields, visibility modes, consent, outputs, duplicate rule, category lookup, and auth are all front-loaded in a single dense paragraph with almost no filler. It runs long, and the visibility pricing/review details could be trimmed, but nearly every sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 27-parameter, 10-required creation tool, the description covers the decisions an agent cannot infer from structured fields: auth scope, review/refund flow, consent requirement, duplicate handling, and prerequisites. With an output schema present, return-value explanation is correctly left minimal.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3, and the description adds cross-field semantics the schema only states per-parameter: consent must be asked before passing withdrawal_consent, and logo_url/ai_usage are called out as mandatory. However, it only spotlights a fraction of the 27 parameters, relying on the schema for the rest.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb+resource+scope: 'Create a new listing in the Tulimoa directory ... on behalf of the authenticated user.' It implicitly distinguishes itself from edit_listing by stating that 'a website that is already listed cannot be submitted again', letting an agent separate creation from modification without opening either schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives explicit routing ('Use list_categories first to pick a valid category id'), a when-not condition (already-listed websites cannot be resubmitted), prerequisites ('Requires a write-scoped Tulimoa login'), and a decision rule between the two visibility modes with their cost and review behavior. Little is left to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.