diff --git a/apps/web/src/lib/config.ts b/apps/web/src/lib/config.ts
index 8945a976..55855d8d 100644
--- a/apps/web/src/lib/config.ts
+++ b/apps/web/src/lib/config.ts
@@ -16,8 +16,7 @@ export const copyright = `© ${new Date().getFullYear()} Agentic. All rights res
export const githubUrl = 'https://github.com/transitive-bullshit/agentic'
// TODO: make an agentic-specific calendar for this
-export const calendarBookingUrl =
- 'https://cal.com/travis-fischer/15min?overlayCalendar=true'
+export const calendarBookingUrl = 'https://cal.com/travis-fischer/15min'
export const docsUrl = 'https://docs.agentic.so'
export const docsQuickStartUrl = `${docsUrl}/quick-start`
export const docsMarketplaceUrl = `${docsUrl}/marketplace`
diff --git a/docs/contact.mdx b/docs/contact.mdx
new file mode 100644
index 00000000..b932fbfd
--- /dev/null
+++ b/docs/contact.mdx
@@ -0,0 +1,25 @@
+---
+title: Contact
+---
+
+Agentic's currently a solo team built and run by [Travis Fischer](https://x.com/transitive_bs). 👋
+
+
+
+
+
+
+
+**TODO**
diff --git a/docs/docs.json b/docs/docs.json
index 799e9c59..57d8f9cd 100644
--- a/docs/docs.json
+++ b/docs/docs.json
@@ -10,6 +10,10 @@
"background": {
"image": "/media/bg.png"
},
+ "appearance": {
+ "mode": "light",
+ "strict": true
+ },
"colors": {
"primary": "#0D969D",
"light": "#13D3DC",
@@ -39,7 +43,7 @@
"groups": [
{
"group": "Getting Started",
- "pages": ["index"]
+ "pages": ["index", "marketplace/index"]
}
]
},
@@ -48,7 +52,32 @@
"groups": [
{
"group": "Getting Started",
- "pages": ["publishing/index"]
+ "pages": [
+ "publishing/index",
+ "publishing/quickstart",
+ "publishing/origin-metadata"
+ ]
+ },
+ {
+ "group": "Publishing Guides",
+ "pages": [
+ "publishing/guides/existing-mcp-server",
+ "publishing/guides/existing-openapi-service",
+ "publishing/guides/ts-mcp-hono",
+ "publishing/guides/ts-openapi-hono"
+ ]
+ },
+ {
+ "group": "Config",
+ "pages": [
+ "publishing/config/index",
+ "publishing/config/auth",
+ "publishing/config/pricing",
+ "publishing/config/rate-limits",
+ "publishing/config/caching",
+ "publishing/config/tool-config",
+ "publishing/config/examples"
+ ]
}
]
}
@@ -61,7 +90,7 @@
"icon": "house"
},
{
- "anchor": "Marketplace",
+ "anchor": "MCP Marketplace",
"href": "https://agentic.so/marketplace",
"icon": "store"
},
diff --git a/docs/index.mdx b/docs/index.mdx
index e8bb3bb6..76015003 100644
--- a/docs/index.mdx
+++ b/docs/index.mdx
@@ -1,15 +1,17 @@
---
title: Home
-description: Agentic is the app store for LLM tools.
+description: Agentic is the App Store for LLM Tools.
---
- The Agentic MCP Marketplace is a curated collection of high quality LLM
- tools – all of which are exposed as both MCP servers and simple HTTP APIs.
+ Agentic's marketplace is a curated collection of high quality LLM tools
+ – all of which are exposed as both MCP servers and simple HTTP APIs.
-
+
Publish any MCP server or OpenAPI service to Agentic's MCP Marketplace and
offer your LLM tools as products to an audience of over 20k AI engineers.
+
+**TODO**
diff --git a/docs/marketplace/index.mdx b/docs/marketplace/index.mdx
new file mode 100644
index 00000000..914a6347
--- /dev/null
+++ b/docs/marketplace/index.mdx
@@ -0,0 +1,23 @@
+---
+title: Quick Start
+description: A quick start guide to using MCP tools on the Agentic marketplace.
+---
+
+
+
+ TODO
+
+
+ TODO
+
+
+
+**TODO**
diff --git a/docs/publishing/config/auth.mdx b/docs/publishing/config/auth.mdx
new file mode 100644
index 00000000..e8578a89
--- /dev/null
+++ b/docs/publishing/config/auth.mdx
@@ -0,0 +1,86 @@
+---
+title: Auth Config
+description: Configure auth for your Agentic product.
+---
+
+Ship to production fast with Agentic's free, hosted authentication. Email & password, OAuth, GitHub, Google, Twitter, etc – if your origin API requires OAuth credentials, Agentic likely already supports it, and if not, [please let us know](/contact).
+
+Currently, Agentic supports the following auth providers:
+
+- Email & password
+- GitHub
+
+## How it works
+
+Your product's users will sign into Agentic, subscribe to your product using Stripe, and then be given an API key to use with their tool calls.
+
+Agentic's MCP gateway will then track all usage of your product based on API keys.
+
+
+
+Agentic's MCP Gateway will always include the following metadata in all tool calls within the `_meta.agentic` field.
+
+```ts
+export type AgenticMcpRequestMetadata = {
+ agenticProxySecret: string
+ sessionId: string
+ isCustomerSubscriptionActive: boolean
+
+ customerId?: string
+ customerSubscriptionStatus?: string
+ customerSubscriptionPlan?: string
+
+ userId?: string
+ userEmail?: string
+ userUsername?: string
+ userName?: string
+ userCreatedAt?: string
+ userUpdatedAt?: string
+
+ deploymentId: string
+ deploymentIdentifier: string
+ projectId: string
+ projectIdentifier: string
+
+ ip?: string
+} & (
+ | {
+ // If the customer has an active subscription, these fields are guaranteed
+ // to be present in the metadata.
+ isCustomerSubscriptionActive: true
+
+ customerId: string
+ customerSubscriptionStatus: string
+
+ userId: string
+ userEmail: string
+ userUsername: string
+ userCreatedAt: string
+ userUpdatedAt: string
+ }
+ | {
+ // If the customer does not have an active subscription, then the customer
+ // fields may or may not be present.
+ isCustomerSubscriptionActive: false
+ }
+)
+```
+
+If a customer doesn't provide an API key, they'll default to your `free` pricing plan with `isCustomerSubscriptionActive` set to `false`.
+
+
+
+TODO
+
+
+## Alpha Features
+
+### MCP OAuth
+
+Agentic's MCP Gateway is designed to interop with MCP's built-in OAuth support, but this functionality is currently in alpha and not enabled publicly by default. If you're interested in using your origin server's MCP authentication support, [please let us know](/contact).
+
+### Custom OAuth Providers
+
+Agentic's MCP Gateway is designed to support any third-party OAuth provider (Google, Twitter / X, Slack, Airtable, Shopify, etc), but this functionality is currently in alpha and not enabled publicly by default.
+
+If you're interested in using a different OAuth provider or want your customers to use your own OAuth client credentials or custom scopes, [please let us know](/contact).
diff --git a/docs/publishing/config/caching.mdx b/docs/publishing/config/caching.mdx
new file mode 100644
index 00000000..f09a0a11
--- /dev/null
+++ b/docs/publishing/config/caching.mdx
@@ -0,0 +1,94 @@
+---
+title: Caching Config
+description: Configure caching for your Agentic product's tools.
+---
+
+Opt-in to caching with familiar _cache-control_ and _stale-while-revalidate_ options. MCP tool calls include caching information in their _\_meta_ fields, providing parity with standard HTTP headers.
+
+Agentic uses Cloudflare's global edge cache for caching, which guarantees unmatched global performance.
+
+## Enabling Caching
+
+You can enable caching for individual tools by setting [pure](/publishing/config/tool-config#param-pure) or [cacheControl](/publishing/config/tool-config#param-cache-control) on the tool's config.
+
+## Cache Keys
+
+Cache keys for tool calls are generated by normalizing the tool call's input, regardless of whether the tool call was made via `HTTP POST`, `HTTP GET`, or `MCP`.
+
+Tool call args will be hashed using a deterministic, stable JSON serialization algorithm, so tool calls with semantically identical input will have identical cache keys.
+
+## Disabling Caching
+
+Individual tool calls can disable caching by setting the standard `Cache-Control` header to `no-store` or `no-cache`.
+
+
+ Note that by default, caching is disabled for all tools. You must explicitly
+ enable caching for each tool in your Agentic project config.
+
+
+## Examples
+
+
+
+
+```ts agentic.config.ts
+import { defineConfig } from '@agentic/platform'
+
+// In this example, `my-tool` is marked as pure which means its responses
+// will be cached aggressively for identical requests using `cache-control`
+// `public, max-age=31560000, s-maxage=31560000, stale-while-revalidate=3600`
+export default defineConfig({
+ // ...
+ toolConfigs: [
+ {
+ name: 'my-tool',
+ pure: true
+ }
+ ]
+})
+```
+
+
+
+
+
+```ts agentic.config.ts
+import { defineConfig } from '@agentic/platform'
+
+// In this example, `my-tool` is using a custom `Cache-Control` header to
+// cache responses for 60 seconds.
+export default defineConfig({
+ // ...
+ toolConfigs: [
+ {
+ name: 'my-tool',
+ cacheControl: 'public, max-age=60, s-maxage=60 stale-while-revalidate=10'
+ }
+ ]
+})
+```
+
+
+
+
+
+```ts agentic.config.ts
+import { defineConfig } from '@agentic/platform'
+
+// In this example, `my-tool` results will never be cached.
+// Note that this is the default behavior for all tools unless caching is
+// explicitly enabled for a tool.
+export default defineConfig({
+ // ...
+ toolConfigs: [
+ {
+ name: 'my-tool',
+ cacheControl: 'no-cache'
+ }
+ ]
+})
+```
+
+
+
+
diff --git a/docs/publishing/config/examples.mdx b/docs/publishing/config/examples.mdx
new file mode 100644
index 00000000..c9effbd0
--- /dev/null
+++ b/docs/publishing/config/examples.mdx
@@ -0,0 +1,6 @@
+---
+title: Examples
+description: Example Agentic config files.
+---
+
+**TODO**
diff --git a/docs/publishing/config/index.mdx b/docs/publishing/config/index.mdx
new file mode 100644
index 00000000..c00ff345
--- /dev/null
+++ b/docs/publishing/config/index.mdx
@@ -0,0 +1,169 @@
+---
+title: Overview
+description: Configuring your Agentic project.
+---
+
+Every Agentic project needs a config file (`agentic.config.ts`, `agentic.config.js`, or `agentic.config.json`) to define the project's metadata, pricing, rate-limits, and any tool-specific behavior overrides.
+
+
+ Configuring your project can feel a little overwhelming. Feel free to [reach
+ out to us](/contact) if you're considering using Agentic's MCP Gateway, and
+ I'd be happy to help walk you through getting your product set up for success.
+
+
+## Config Fields
+
+
+Display name for your project.
+
+Max length 1024 characters.
+
+
+
+
+Unique project slug.
+
+Must be ascii-only, lower-case, and kebab-case with no spaces between 1 and 256 characters.
+
+The project's fully qualified identifier will be `@namespace/slug`, where
+the `namespace` is determined by the author's `username` or team slug.
+
+If not provided, it will be derived by slugifying `name`.
+
+
+
+
+ Short description of the project.
+
+Should be no longer than a few lines.
+
+
+
+
+Optional semantic version of the project as a [semver](https://semver.org) string.
+
+Examples: `1.0.0`, `0.0.1`, `5.0.1`, etc.
+
+
+
+
+ Optional embedded markdown readme documenting the project. Supports
+ GitHub-flavored markdown.
+
+
+
+ Optional logo image URL to use for the project. Logos should have a square
+ aspect ratio.
+
+
+
+
+ Optional URL to the source code of the project (eg, GitHub repo).
+
+
+
+ Origin API adapter used to configure the origin API server downstream from
+ Agentic's API gateway.
+
+
+
+
+
+ The type of origin server. `mcp` in this case.
+
+
+
+
+Required base URL of the externally hosted origin MCP server.
+
+This URL must be accessible from Agentic's API gateway and support the Streamable HTTP transport.
+
+Must be a valid `https` URL.
+
+
+
+
+
+
+
+ The type of origin server. `openapi` in this case.
+
+
+
+
+Required base URL of the externally hosted origin API server.
+
+Must be a valid `https` URL.
+
+
+
+
+
+Local file path or URL to an OpenAPI 3.x spec describing the origin API server.
+
+May also be an embedded string containing a JSON stringified OpenAPI 3.x spec.
+
+Note that older OpenAPI versions are not supported.
+
+
+
+
+
+
+
+
+ List of PricingPlans configuring which Stripe subscriptions should be available for the project.
+
+Defaults to a single free plan which is useful for developing and testing your project.
+
+See [PricingPlan](/publishing/config/pricing#pricing-plan-config) for details.
+
+
+
+
+Optional list of billing intervals to enable in pricing plans.
+
+Defaults to a single monthly interval `['month']`.
+
+To add support for annual pricing plans, for example, you can use:
+`['month', 'year']`.
+
+Note that for every pricing interval, you must define a corresponding set
+of PricingPlans in the `pricingPlans` array. If you only have one pricing
+interval (like the default `month` interval), `pricingPlans` don't need to
+specify their `interval` property. Otherwise, all PricingPlans must
+specify their `interval` property to differentiate between different
+pricing intervals.
+
+
+
+
+Optional default rate limits to enforce across all pricing plans.
+
+If not set, a default platform rate-limit of 1000 requests per minute per customer will be used.
+
+To disable the default rate-limit, set `defaultRateLimit.enabled` to
+`false`.
+
+Note that pricing-plan-specific rate-limits override this default (via
+`pricingPlans`), and tool-specific rate-limits may override both default
+and pricing-plan-specific rate-limits (via `toolConfigs`).
+
+See [Rate Limits](/publishing/config/rate-limits) for more details.
+
+
+
+
+Optional list of tool configs to override the default behavior of specific tools.
+
+See [Tool Config](/publishing/config/tool-config) for details.
+
+
+
+## Config Help
+
+
+ Configuring your project can feel a little overwhelming. Feel free to [reach
+ out to us](/contact) if you're considering using Agentic's MCP Gateway, and
+ I'd be happy to help walk you through getting your product set up for success.
+
diff --git a/docs/publishing/config/pricing.mdx b/docs/publishing/config/pricing.mdx
new file mode 100644
index 00000000..246fa607
--- /dev/null
+++ b/docs/publishing/config/pricing.mdx
@@ -0,0 +1,428 @@
+---
+title: Pricing Config
+description: Configure pricing for your Agentic product.
+---
+
+Charge for your Agentic product with a flexible, declarative pricing model built on top of [Stripe](https://stripe.com).
+
+Agentic supports almost any combination of **fixed** and **usage-based billing** billing models, both at the MCP level, at the tool-call level, and at the custom metric level (e.g., tokens, image transformations, etc).
+
+
+ Pricing can feel a little complicated to set up. Feel free to [reach out to
+ us](/contact) once you're ready to start charging for your product, and I'd be
+ happy to help you set everything up.
+
+
+## Pricing Plan Config
+
+
+Display name for the pricing plan.
+
+Examples: "Free", "Starter Monthly", "Pro Annual", etc.
+
+
+
+
+A unique slug for the pricing plan which acts as a stable identifier across deployments.
+
+Should be lower-kebab-cased.
+Should be stable across deployments.
+
+For all plans aside from `free`, the `slug` should include the `interval`
+as a suffix so pricing plans can be uniquely differentiated from each
+other across billing intervals.
+
+Examples: `free`, `starter-monthly`, `pro-annual`, etc.
+
+
+
+
+The frequency at which this subscription is billed.
+
+One of `day`, `week`, `month`, or `year`.
+
+[Stripe docs](https://docs.stripe.com/api/prices/object?api-version=2025-02-24.acacia#price_object-recurring-interval)
+
+
+
+
+ Optional description of the pricing plan (UI-only).
+
+
+
+ Optional list of features of the pricing plan (UI-only; array of strings).
+
+
+
+ Optional number of days for a free trial period when a customer signs up for a
+ new subscription.
+
+[Stripe docs](https://docs.stripe.com/api/subscriptions/create?api-version=2025-05-28.preview#create_subscription-trial_period_days)
+
+
+
+
+Optional rate limit to enforce for customers on this pricing plan.
+
+You can use this to limit the number of API requests that can be made by
+a customer during a given interval.
+
+If not set, the pricing plan will inherit the default platform rate-limit
+set by `defaultRateLimit` in the Agentic project config.
+
+You can disable rate-limiting for this pricing plan by setting
+`rateLimit.enabled` to `false`.
+
+See [Rate Limits](/publishing/config/rate-limits) for more details.
+
+
+
+
+List of LineItems which are included in the PricingPlan.
+
+Note: Agentic currently supports a max of 20 LineItems per pricing plan.
+
+See [PricingPlanLineItem](#pricing-plan-line-item-config) for details.
+
+
+
+## Pricing Plan Line Item Config
+
+Each Pricing Plan Line Item corresponds to one [Stripe Product](https://docs.stripe.com/api/products/object?api-version=2025-05-28.preview), one [Stripe Price](https://docs.stripe.com/api/prices/object?api-version=2025-05-28.preview), and possibly one [Stripe Meter](https://docs.stripe.com/api/billing/meter/object?api-version=2025-05-28.preview) if the line-item is `metered`.
+
+
+Slugs act as the primary key for LineItems. They should be lower-cased and
+kebab-cased ("base", "requests", "image-transformations").
+
+The `base` slug is reserved for a plan's default `licensed` line-item.
+
+The `requests` slug is reserved for charging using `metered` billing based
+on the number of request made during a given billing interval.
+
+All other PricingPlanLineItem `slugs` are considered custom LineItems.
+
+Should be stable across deployments, so if a slug refers to one type of
+product / line-item / metric in one deployment, it should refer to the same
+product / line-item / metric in future deployments, even if they are
+configured differently. If you are switching between a licensed and metered
+line-item across deployments, they must use different slugs.
+
+
+
+
+Optional label for the line-item which will be displayed on customer bills.
+
+If unset, the line-item's `slug` will be used as the label.
+
+[Stripe Docs](https://docs.stripe.com/api/products/object?api-version=2025-02-24.acacia#product_object-unit_label)
+
+
+
+
+ The type of usage to charge for. Either `licensed` or `metered`.
+
+[Stripe docs](https://docs.stripe.com/api/prices/object?api-version=2025-02-24.acacia#price_object-recurring-usage_type)
+
+
+
+
+
+Licensed line-items are used to charge for **fixed-price services**.
+
+
+ The type of usage to charge for. `licensed` in this case.
+
+[Stripe docs](https://docs.stripe.com/api/prices/object?api-version=2025-02-24.acacia#price_object-recurring-usage_type)
+
+
+
+
+The fixed amount to charge per billing interval.
+
+Specified in the smallest currency unit (e.g. cents for USD).
+
+So 100 = \$1.00 USD, 1000 = \$10.00 USD, etc.
+
+[Stripe docs](https://docs.stripe.com/api/prices/create?api-version=2025-05-28.preview#create_price-unit_amount)
+
+
+
+
+
+Metered line-items are used to charge for **usage-based services**.
+
+
+ The type of usage to charge for. `metered` in this case.
+
+[Stripe docs](https://docs.stripe.com/api/prices/object?api-version=2025-02-24.acacia#price_object-recurring-usage_type)
+
+
+
+
+Optional label for the line-item which will be displayed on customer bills.
+
+If unset, the line-item's `slug` will be used as the unit label.
+
+[Stripe Docs](https://docs.stripe.com/api/products/object?api-version=2025-02-24.acacia#product_object-unit_label)
+
+
+
+
+Describes how to compute the price per period. Either `per_unit` or `tiered`.
+
+`per_unit` indicates that the fixed amount (specified in `unitAmount`) will be charged per unit of total usage.
+
+`tiered` indicates that the unit pricing will be computed using a tiering strategy as defined using `tiers` and `tiersMode`.
+
+[Stripe docs](https://docs.stripe.com/api/prices/object?api-version=2025-02-24.acacia#price_object-billing_scheme)
+
+
+
+
+The fixed amount to charge per unit of usage.
+
+Only applicable for `per_unit` billing schemes.
+
+Specified in the smallest currency unit (e.g. cents for USD).
+
+So 100 = \$1.00 USD, 1000 = \$10.00 USD, etc.
+
+[Stripe docs](https://docs.stripe.com/api/prices/object?api-version=2025-02-24.acacia#price_object-unit_amount)
+
+
+
+
+Defines if the tiering price should be `graduated` or `volume` based.
+
+In `volume`-based tiering, the maximum quantity within a period
+determines the per unit price.
+
+In `graduated`-based tiering, the per-unit price changes successively
+as the quantity grows.
+
+This field requires `billingScheme` to be set to `tiered`.
+
+[Stripe docs](https://docs.stripe.com/api/prices/object?api-version=2025-02-24.acacia#price_object-tiers_mode)
+
+
+
+
+Pricing tiers for `tiered` billing schemes.
+
+This field requires `billingScheme` to be set to `tiered`.
+
+One of `unitAmount` or `flatAmount` must be provided, but not both.
+
+[Stripe docs](https://docs.stripe.com/api/prices/object?api-version=2025-02-24.acacia#price_object-tiers)
+
+
+
+ The maximum quantity of usage for this tier.
+
+Should be a number or `inf` for the maximum tier.
+
+
+
+
+The fixed amount to charge per unit of usage for this pricing tier.
+
+Specified in the smallest currency unit (e.g. cents for USD).
+
+So 100 = \$1.00 USD, 1000 = \$10.00 USD, etc.
+
+
+
+
+The fixed amount to charge per billing interval for this pricing tier.
+
+Specified in the smallest currency unit (e.g. cents for USD).
+
+So 100 = \$1.00 USD, 1000 = \$10.00 USD, etc.
+
+
+
+
+
+
+
+
+Specifies how events are aggregated for the Stripe Meter.
+
+[Stripe docs](https://docs.stripe.com/api/billing/meter/create?api-version=2025-02-24.acacia#create_billing_meter-default_aggregation)
+
+
+
+Specifies how events are aggregated for a Stripe Meter.
+
+Allowed values:
+
+- `sum` - Sum each event's value during the period.
+- `count` - Count the number of events during the period.
+
+If not set, `sum` will be used.
+
+
+
+
+
+
+
+
+Optional transformation to apply to the reported usage or set quantity before computing the amount billed.
+
+Cannot be combined with `tiers`.
+
+[Stripe docs](https://docs.stripe.com/api/prices/object?api-version=2025-02-24.acacia#price_object-transform_quantity)
+
+
+
+Divide usage by this number.
+
+Must be a positive number.
+
+[Stripe docs](https://docs.stripe.com/api/prices/object?api-version=2025-02-24.acacia#price_object-transform_quantity-divide_by)
+
+
+
+
+After division, either round the result `up` or `down`.
+
+[Stripe docs](https://docs.stripe.com/api/prices/object?api-version=2025-02-24.acacia#price_object-transform_quantity-round)
+
+
+
+
+
+
+
+
+
+
+
+## Example Pricing Plans
+
+
+
+
+This example shows a free monthly pricing plan which is used by default for projects that don't specify any pricing plans.
+
+```ts agentic.config.ts
+import { defineConfig } from '@agentic/platform'
+
+export default defineConfig({
+ // ...
+ pricingPlans: [
+ {
+ name: 'Free',
+ slug: 'free',
+ lineItems: [
+ {
+ slug: 'base',
+ usageType: 'licensed',
+ amount: 0
+ }
+ ]
+ }
+ ]
+})
+```
+
+
+
+
+
+This example has 2 pricing plans, the default free plan and a fixed-price $4.99 / month basic plan with a 7-day trial.
+
+```ts agentic.config.ts
+import { defaultFreePricingPlan, defineConfig } from '@agentic/platform'
+
+export default defineConfig({
+ // ...
+ pricingPlans: [
+ defaultFreePricingPlan,
+ {
+ name: 'Basic',
+ slug: 'basic',
+ trialPeriodDays: 7,
+ lineItems: [
+ {
+ slug: 'base',
+ usageType: 'licensed',
+ amount: 499 // $4.99 USD
+ }
+ ]
+ }
+ ]
+})
+```
+
+
+
+
+
+```ts agentic.config.ts
+import { defineConfig } from '@agentic/platform'
+
+export default defineConfig({
+ // ...
+ pricingPlans: [
+ {
+ name: 'Free',
+ slug: 'free',
+ lineItems: [
+ {
+ slug: 'base',
+ usageType: 'licensed',
+ amount: 0
+ }
+ ],
+ // Free but limited to 20 requests per day
+ rateLimit: {
+ limit: 20,
+ interval: '1d'
+ }
+ },
+ {
+ name: 'Pay-As-You-Go',
+ slug: 'pay-as-you-go',
+ lineItems: [
+ {
+ slug: 'requests',
+ usageType: 'metered',
+ billingScheme: 'tiered',
+ tiersMode: 'volume',
+ // $0.00467 USD per request up to 999 requests per month
+ // then $0.00053 USD for unlimited further requests that month
+ tiers: [
+ {
+ upTo: 999,
+ unitAmount: 0.467
+ },
+ {
+ upTo: 'inf',
+ unitAmount: 0.053
+ }
+ ]
+ }
+ ],
+ // Limit to 1000 requests per day
+ rateLimit: {
+ limit: 1000,
+ interval: '1d'
+ }
+ }
+ ]
+})
+```
+
+
+
+
+
+## Pricing Help
+
+
+ Pricing can feel a little complicated to set up. Feel free to [reach out to
+ us](/contact) once you're ready to start charging for your product, and I'd be
+ happy to help you set everything up.
+
diff --git a/docs/publishing/config/rate-limits.mdx b/docs/publishing/config/rate-limits.mdx
new file mode 100644
index 00000000..72113f49
--- /dev/null
+++ b/docs/publishing/config/rate-limits.mdx
@@ -0,0 +1,86 @@
+---
+title: Rate Limit Config
+description: Configure rate-limits for your Agentic product.
+---
+
+Agentic's durable rate-limiting is built on top of Cloudflare's global infrastructure. Customize the default rate-limits, change them based on a customer's pricing plan, or create custom tool-specific overrides.
+
+## Rate Limit Config
+
+
+ Whether to enable rate limiting for this pricing plan.
+
+
+
+ The interval at which the rate limit is applied.
+
+Either a positive integer expressed in seconds or a valid positive [ms](https://github.com/vercel/ms) string (eg, "10s", "1m", "8h", "2d", "1w", "1y", etc).
+
+
+
+
+ The maximum number of API requests per interval (unitless).
+
+
+
+ How to enforce the rate limit: "strict" (more precise but slower) or "approximate" (the default; faster and asynchronous but less precise).
+
+The default rate-limiting mode is `approximate`, which means that requests
+are allowed to proceed immediately, with the limit being enforced
+asynchronously in the background. This is much faster than synchronous
+mode, but it is less consistent if precise adherence to rate-limits is
+required.
+
+With `strict` mode, requests are blocked until the current limit has
+been confirmed. The downside with this approach is that it introduces
+more latency to every request by default. The advantage is that it is
+more precise and consistent.
+
+
+
+## Example Rate Limits
+
+
+
+
+The default platform rate limit for `requests` is a limit of 1000 requests per minute per customer.
+
+```ts
+{
+ enabled: true,
+ interval: '1m',
+ limit: 1000,
+ mode: 'approximate'
+}
+```
+
+
+
+
+
+This example rate limit restricts customers to 100 requests per day. It uses `strict` mode which adds a little extra latency but guarantees that customers will never exceed the limit.
+
+```ts
+{
+ enabled: true,
+ interval: '1d',
+ limit: 100,
+ mode: 'strict'
+}
+```
+
+
+
+
+
+This is an example of a disabled rate limit.
+
+```ts
+{
+ enabled: false
+}
+```
+
+
+
+
diff --git a/docs/publishing/config/tool-config.mdx b/docs/publishing/config/tool-config.mdx
new file mode 100644
index 00000000..255fd0b2
--- /dev/null
+++ b/docs/publishing/config/tool-config.mdx
@@ -0,0 +1,153 @@
+---
+title: Tool Config
+description: Configure tool-specific settings for your Agentic product.
+---
+
+Optional list of tool configs to override the default behavior of specific tools.
+
+Make sure the tool `name` matches the origin server's tool names, either via its MCP server or OpenAPI operationIds.
+
+Tool names are expected to be unique and stable across deployments.
+
+With `toolConfigs`, tools can be disabled, set custom rate-limits, customize reporting usage for metered billing, and they can also override behavior for different pricing plans.
+
+For example, you may want to disable certain tools on a `free` pricing plan or remove the rate-limit for a specific tool on a `pro` pricing plan while keeping the defualt rate-limit in place for other tools.
+
+Note that tool-specific configs override the defaults defined in pricing plans.
+
+If a tool is defined on the origin server but not specified in `toolConfigs`, it will use the default behavior of the Agentic API gateway.
+
+## Tool Config
+
+
+ The name of the tool, which acts as a unique, stable identifier for the tool
+ across deployments.
+
+
+
+Whether this tool should be enabled for all customers (default).
+
+If you want to hide a tool from customers but still have it present on your origin server, set this to `false` for the given tool.
+
+
+
+
+Whether this tool's output is deterministic and idempotent given the same input.
+
+If `true`, tool outputs will be cached aggressively for identical requests, though origin server response headers can still override this behavior on a per-request basis.
+
+If `false`, tool outputs will be cached according to the origin server's response headers on a per-request basis.
+
+
+
+
+A custom `Cache-Control` header to use for caching this tool's responses.
+
+If set, this field overrides `pure`.
+
+If not set and `pure` is `true`, the gateway will default to: `public, max-age=31560000, s-maxage=31560000, stale-while-revalidate=3600` (cache publicly for up to 1 year).
+
+If not set and `pure` is `false`, the gateway will default to `no-store` which will disable caching. This is the default gateway behavior for tools (no caching).
+
+Note that origin server response headers may also choose to disable caching on a per-request basis.
+
+
+
+
+Whether calls to this tool should be reported as usage for the default `requests` line-item's metered billing.
+
+Note: This is only relevant if the customer's active pricing plan includes a `requests` line-item.
+
+
+
+
+Customize the default `requests`-based rate-limiting for this tool.
+
+To disable rate-limiting for this tool, set `rateLimit.enabled` to `false`.
+
+If not set, the default rate-limiting for the active pricing plan will be used.
+
+See [Rate Limits](/publishing/config/rate-limits) for details.
+
+
+
+
+Whether to allow additional properties in the tool's input schema.
+
+The default MCP spec allows additional properties. Set this to `false` if you want your tool to be more strict.
+
+Note: This is only relevant if the tool has defined an `inputSchema`.
+
+
+
+
+Whether to allow additional properties in the tool's output schema.
+
+The default MCP spec allows additional properties. Set this to `false` if you want your tool to be more strict.
+
+Note: This is only relevant if the tool has defined an `outputSchema`.
+
+
+
+
+Allows you to override this tool's behavior or disable it entirely for different pricing plans.
+
+This is a map from PricingPlan `slug` to PricingPlanToolOverride.
+
+```ts agentic.config.ts
+import { defineConfig } from '@agentic/platform'
+
+// In this example, `my-tool` is disabled for the `free` pricing plan.
+export default defineConfig({
+ // ...
+ toolConfigs: [
+ {
+ name: 'my-tool',
+ pricingPlanOverridesMap: {
+ free: {
+ enabled: false
+ }
+ }
+ }
+ ]
+})
+```
+
+
+
+ Whether this tool should be enabled for the given pricing plan.
+
+ If `undefined`, will use the tool's default enabled state.
+
+
+
+
+ Whether to report default `requests` usage for metered billing for customers on a given pricing plan.
+
+ Note: This is only relevant if the pricing plan includes a `requests` line-item.
+
+ If `undefined`, will use the tool's default reportUsage state.
+
+
+
+
+Customize or disable rate limits for this tool for customers on a given pricing plan.
+
+To disable rate-limiting for this tool on a given pricing plan, set `rateLimit.enabled` to `false`.
+
+See [Rate Limits](/publishing/config/rate-limits) for details.
+
+
+
+
+
+
+
+## Config Help
+
+
+ Configuring your project can feel a little overwhelming with the amount of
+ options available. Feel free to [reach out to us](/contact) if you're
+ considering using Agentic's MCP Gateway, and I'd be happy to help walk you
+ through getting your product set up for success.
+
diff --git a/docs/publishing/guides/existing-mcp-server.mdx b/docs/publishing/guides/existing-mcp-server.mdx
new file mode 100644
index 00000000..597d119f
--- /dev/null
+++ b/docs/publishing/guides/existing-mcp-server.mdx
@@ -0,0 +1,6 @@
+---
+title: Existing MCP Server
+description: This guide shows how to publish an existing MCP server to Agentic's MCP Gateway.
+---
+
+**TODO**
diff --git a/docs/publishing/guides/existing-openapi-service.mdx b/docs/publishing/guides/existing-openapi-service.mdx
new file mode 100644
index 00000000..918d1728
--- /dev/null
+++ b/docs/publishing/guides/existing-openapi-service.mdx
@@ -0,0 +1,6 @@
+---
+title: Existing OpenAPI Service
+description: This guide shows how to publish an existing OpenAPI service to Agentic's MCP Gateway.
+---
+
+**TODO**
diff --git a/docs/publishing/guides/ts-mcp-hono.mdx b/docs/publishing/guides/ts-mcp-hono.mdx
new file mode 100644
index 00000000..e72c694e
--- /dev/null
+++ b/docs/publishing/guides/ts-mcp-hono.mdx
@@ -0,0 +1,6 @@
+---
+title: TS MCP Hono
+description: This guide shows how to publish an MCP server to Agentic's MCP Gateway using TypeScript and Hono's MCP middleware.
+---
+
+**TODO**
diff --git a/docs/publishing/guides/ts-openapi-hono.mdx b/docs/publishing/guides/ts-openapi-hono.mdx
new file mode 100644
index 00000000..00a54d5f
--- /dev/null
+++ b/docs/publishing/guides/ts-openapi-hono.mdx
@@ -0,0 +1,6 @@
+---
+title: TS OpenAPI Hono
+description: This guide shows how to publish an OpenAPI service to Agentic's MCP Gateway using TypeScript and Hono's OpenAPI support.
+---
+
+**TODO**
diff --git a/docs/publishing/index.mdx b/docs/publishing/index.mdx
index 4f371c08..75657f15 100644
--- a/docs/publishing/index.mdx
+++ b/docs/publishing/index.mdx
@@ -5,3 +5,5 @@ description: Your API → Paid MCP, Instantly.
Run one command to turn any MCP server or OpenAPI service into a paid MCP
product, with built-in distribution to over 20k AI engineers.
+
+**TODO**
diff --git a/docs/publishing/origin-metadata.mdx b/docs/publishing/origin-metadata.mdx
new file mode 100644
index 00000000..8bf9205e
--- /dev/null
+++ b/docs/publishing/origin-metadata.mdx
@@ -0,0 +1,219 @@
+---
+title: Origin Metadata
+description: Agentic's MCP Gateway passes metadata to your origin server.
+---
+
+
+
+Agentic's MCP Gateway will always include the following metadata in all tool calls within the `_meta.agentic` field.
+
+```ts
+export type AgenticMcpRequestMetadata = {
+ agenticProxySecret: string
+ sessionId: string
+ isCustomerSubscriptionActive: boolean
+
+ customerId?: string
+ customerSubscriptionStatus?: string
+ customerSubscriptionPlan?: string
+
+ userId?: string
+ userEmail?: string
+ userUsername?: string
+ userName?: string
+ userCreatedAt?: string
+ userUpdatedAt?: string
+
+ deploymentId: string
+ deploymentIdentifier: string
+ projectId: string
+ projectIdentifier: string
+
+ ip?: string
+} & (
+ | {
+ // If the customer has an active subscription, these fields are guaranteed
+ // to be present in the metadata.
+ isCustomerSubscriptionActive: true
+
+ customerId: string
+ customerSubscriptionStatus: string
+
+ userId: string
+ userEmail: string
+ userUsername: string
+ userCreatedAt: string
+ userUpdatedAt: string
+ }
+ | {
+ // If the customer does not have an active subscription, then the customer
+ // fields may or may not be present.
+ isCustomerSubscriptionActive: false
+ }
+)
+```
+
+
+
+
+Agentic's MCP Gateway will always include the following headers for all tool calls to your origin server.
+
+
+ The secret key of your Agentic project. This is used to guarantee that HTTP
+ requests are actually coming from Agentic's MCP Gateway, and not from
+ third-party actors.
+
+You can find this secret key in your Agentic project's dashboard settings.
+
+
+
+
+ The ID of the customer in Agentic's database.
+
+
+
+ Whether the customer has an active subscription. Will be either `true` or
+ `false`.
+
+
+
+ The [Stripe status](https://docs.stripe.com/api/subscriptions/object#subscription_object-status) of the customer's subscription.
+
+Possible values are `incomplete`, `incomplete_expired`, `trialing`, `active`, `past_due`, `canceled`, `unpaid`, or `paused`.
+
+
+
+
+ The slug of the customer's subscription pricing plan.
+
+
+
+ The ID of the user in Agentic's database.
+
+
+
+ The email of the user in Agentic's database.
+
+
+
+ The username of the user in Agentic's database.
+
+
+
+ The name of the user in Agentic's database.
+
+
+
+ The date and time the user was created in Agentic's database.
+
+
+
+ The date and time the user was last updated in Agentic's database.
+
+
+
+ The ID of the project in Agentic's database. (`proj_...`)
+
+
+
+ The public identifier of the target project in Agentic's database.
+ (`@username/project-name`)
+
+
+
+ The ID of the target deployment in Agentic's database. (`depl_...`)
+
+
+
+ The public identifier of the target deployment in Agentic's database.
+ (`@username/project-name@`)
+
+
+
+
+## Unauthenticated requests
+
+If a customer doesn't provide an API key for their MCP or HTTP call, Agentic's MCP Gateway will default them to your project's `free` pricing plan with `isCustomerSubscriptionActive` set to `false`.
+
+This means they'll be subject to your project's `free` pricing plan's [rate limits](/publishing/config/rate-limits), which is important to protect your origin server from abuse.
+
+## Securing your origin server
+
+Agentic's MCP Gateway will always pass a proxy secret when making tool calls to your origin server (either as `_meta.agentic.agenticProxySecret` for MCP origin servers or as an `x-agentic-proxy-secret` header for OpenAPI origin servers).
+
+You can find this secret key in your Agentic project's dashboard settings.
+
+You'll want to set this secret key in your origin server's environment variables and use it to protect against unauthorized requests.
+
+Note that this is only necessary if your origin server is deployed externally to a public network.
+
+### Securing an MCP origin server
+
+```ts
+// This is example pseudocode for how you might protect your origin MCP
+// server to ensure only calls from Agentic's MCP Gateway are allowed.
+if (
+ (_meta?.agentic as any)?.agenticProxySecret !==
+ process.env.AGENTIC_PROXY_SECRET
+) {
+ return {
+ content: [
+ {
+ type: 'text',
+ text: 'Unauthorized'
+ }
+ ]
+ }
+}
+```
+
+### Securing an OpenAPI origin server
+
+```ts
+// This is example pseudocode for how you might protect your origin OpenAPI
+// service to ensure only calls from Agentic's MCP Gateway are allowed.
+if (
+ request.headers.get('x-agentic-proxy-secret') !==
+ process.env.AGENTIC_PROXY_SECRET
+) {
+ return {
+ status: 401,
+ body: {
+ error: 'Unauthorized'
+ }
+ }
+}
+```
+
+### Restricting IP addresses
+
+You can also protecting your origin server by restricting HTTP calls to specific IP addresses used by Agentic's MCP gateway.
+
+This is currently a private beta feature. If you're interested in using it, please [get in touch](/contact).
+
+### Signed HTTP requests
+
+You can also protecting your origin OpenAPI server by requiring all HTTP requests to be signed with your project's proxy secret.
+
+This is currently a private beta feature. If you're interested in using it, please [get in touch](/contact).
+
+### Signed MCP requests
+
+[MCP currently doesn't support signed requests](https://github.com/modelcontextprotocol/modelcontextprotocol/discussions/461).
+
+If you're interested in this feature, please [get in touch](/contact).
diff --git a/docs/publishing/quickstart.mdx b/docs/publishing/quickstart.mdx
new file mode 100644
index 00000000..e81b2e28
--- /dev/null
+++ b/docs/publishing/quickstart.mdx
@@ -0,0 +1,6 @@
+---
+title: Quick Start
+description: Run one command to turn your existing MCP server or OpenAPI service into a paid MCP product.
+---
+
+**TODO**
diff --git a/examples/search/agentic.config.ts b/examples/search/agentic.config.ts
index 3433aac7..b6a1f347 100644
--- a/examples/search/agentic.config.ts
+++ b/examples/search/agentic.config.ts
@@ -38,6 +38,11 @@ export default defineConfig({
name: 'Standard',
slug: 'standard',
lineItems: [
+ {
+ slug: 'base',
+ usageType: 'licensed',
+ amount: 1000
+ },
{
slug: 'requests',
usageType: 'metered',
diff --git a/examples/search/src/worker.ts b/examples/search/src/worker.ts
index 5db4c03d..a75c0b7b 100644
--- a/examples/search/src/worker.ts
+++ b/examples/search/src/worker.ts
@@ -72,11 +72,6 @@ export default {
.passthrough().shape
},
async (args, { _meta }) => {
- console.log('search call', {
- args,
- _meta
- })
-
// Make sure the request is coming from Agentic
if (
(_meta?.agentic as any)?.agenticProxySecret !==
diff --git a/packages/fixtures/valid/basic-mcp/agentic.config.ts b/packages/fixtures/valid/basic-mcp/agentic.config.ts
index 0521715a..8580da38 100644
--- a/packages/fixtures/valid/basic-mcp/agentic.config.ts
+++ b/packages/fixtures/valid/basic-mcp/agentic.config.ts
@@ -1,8 +1,7 @@
import { defineConfig } from '@agentic/platform'
export default defineConfig({
- name: 'Test Basic MCP',
- slug: 'test-basic-mcp',
+ name: 'test-basic-mcp',
origin: {
type: 'mcp',
url: 'https://agentic-basic-mcp-test.onrender.com/mcp'
diff --git a/packages/types/src/agentic-project-config.ts b/packages/types/src/agentic-project-config.ts
index b8d55218..f473dec6 100644
--- a/packages/types/src/agentic-project-config.ts
+++ b/packages/types/src/agentic-project-config.ts
@@ -188,7 +188,7 @@ To add support for annual pricing plans, for example, you can use: \`['month', '
.default(['month']),
/**
- * Optional default rate limits to enforce for all pricing plans.
+ * Optional default rate limits to enforce across all pricing plans.
*
* To disable the default rate-limit, set `defaultRateLimit.enabled` to
* `false`.
@@ -202,7 +202,8 @@ To add support for annual pricing plans, for example, you can use: \`['month', '
.default(defaultRequestsRateLimit),
/**
- * Optional list of tool configs to customize the behavior of tools.
+ * Optional list of tool configs to override the default behavior of
+ * specific tools.
*
* Make sure the tool `name` matches the origin server's tool names, either
* via its MCP server or OpenAPI operationIds.
diff --git a/packages/types/src/pricing.ts b/packages/types/src/pricing.ts
index 4a99f34a..0d0529f3 100644
--- a/packages/types/src/pricing.ts
+++ b/packages/types/src/pricing.ts
@@ -233,14 +233,13 @@ export const pricingPlanMeteredLineItemSchema =
.object({
/**
* Specifies how events are aggregated for a Stripe Meter.
- * Allowed values are `count` to count the number of events, `sum`
- * to sum each event's value and `last` to take the last event's
- * value in the window.
+ * Allowed values are `count` to count the number of events and `sum`
+ * to sum each event's value .
*
* Defaults to `sum`.
*/
formula: z
- .union([z.literal('sum'), z.literal('count'), z.literal('last')])
+ .union([z.literal('sum'), z.literal('count')])
.default('sum')
})
.optional(),
@@ -482,7 +481,7 @@ export const pricingPlanSchema = z
.string()
.nonempty()
.describe(
- 'Human-readable name for the pricing plan (eg, "Free", "Starter Monthly", "Pro Annual", etc)'
+ 'Display name for the pricing plan (eg, "Free", "Starter Monthly", "Pro Annual", etc)'
)
.openapi('name', { example: 'Starter Monthly' }),
@@ -550,13 +549,13 @@ export const pricingPlanSchema = z
rateLimit: rateLimitSchema.optional(),
/**
- * List of custom LineItems which are included in the PricingPlan.
+ * List of LineItems which are included in the PricingPlan.
*
- * Note: we currently support a max of 20 LineItems per plan.
+ * Note: Agentic currently supports a max of 20 LineItems per pricing plan.
*/
lineItems: z.array(pricingPlanLineItemSchema).nonempty().max(20, {
message:
- 'Stripe Checkout currently supports a max of 20 LineItems per subscription.'
+ 'Agentic currently supports a max of 20 LineItems per pricing plan.'
})
})
.describe(