afps-spec

Agent Format Packaging Standard (AFPS) Specification

Copyright © 2026 Appstrate contributors. Licensed under CC-BY-4.0.

Version 2.0 – Draft

Abstract

Agent Format Packaging Standard (AFPS) is an open specification for declaring portable AI workflow packages. It defines a JSON-based manifest format for four package types — agents, skills, MCP servers, and integrations — along with their dependency model, schema system, archive layout, and integration authentication metadata. AFPS standardizes package definition and composition; it does not define tool-calling protocols, agent-to-agent transport, or runtime execution APIs.

AFPS 2.0 adopts a snake_case field vocabulary across all package types, defines an mcp-server package type that is AFPS-native at the root and adopts the MCP Bundle ([MCPB]) field vocabulary for its server, tools, and user-configuration block, and replaces the legacy tool and provider types with mcp-server and integration. See Appendix D for migration from AFPS 1.x.

Status of this Document

This document is a draft of the AFPS v2.0 specification. It is published for community review and early implementation feedback.

This draft is published for community review and early implementation feedback. It is expected to evolve based on implementation experience and community input before reaching a stable release.

Table of Contents


1. Introduction

1.1 Purpose

Agent Format Packaging Standard (AFPS) defines a declarative package format for AI workflows and closely related package types.

The central artifact in AFPS is the agent — a package that captures the user’s intent (via a prompt.md companion file) together with everything the agent needs to fulfill it: skills, MCP servers, integration connections, input and output schemas, and execution settings. An agent execution is non-interactive and run-to-completion: the agent receives the objective, the input data, and the available resources, processes the task autonomously, and returns a structured result. There is no conversational back-and-forth — the agent runs from start to finish without user interaction. Where other standards define agent capabilities (what an agent can do), an AFPS agent defines an objective (what the agent should accomplish).

AFPS also defines three supporting package types — skills (reusable instructions), MCP servers (runnable tool servers, packaged as MCP Bundles), and integrations (credentialed bindings to external services) — that agents compose as dependencies.

The goal of AFPS is to let producers publish portable artifacts that describe:

AFPS is intentionally centered on package definition. It standardizes package metadata and package layout, not runtime execution APIs.

1.2 Scope

This specification defines:

This specification does not define:

AFPS is transport-agnostic: it does not prescribe how packages are fetched, transferred, or cached.

1.2.1 Relationship to Other Standards

AFPS occupies the packaging-and-composition layer: one archive declares an agent’s goal and every skill, MCP server, and integration it depends on, with versioned dependencies between them. Existing AI standards each package a single artifact type (MCPB → one MCP server; Agent Skills → one skill; A2A AgentCard → one runtime agent endpoint); AFPS composes all four artifact types in a single distribution archive.

─────────────────────────────────────────────────────────────
Distribution    AFPS Registry · npm · OCI · any HTTP store     not in spec —
                (hosts versioned .afps archives)               transport-agnostic
─────────────────────────────────────────────────────────────
                                ▲ publish / fetch
─────────────────────────────────────────────────────────────
Packaging       AFPS .afps (ZIP) — manifest.json + companions  this spec
(this spec)       ├── agent       (NEW)
                  ├── skill       (extends Agent Skills)
                  ├── mcp-server  (adopts MCPB vocab)
                  └── integration (source + auths + delivery)
─────────────────────────────────────────────────────────────
                                ▲ consumed by
─────────────────────────────────────────────────────────────
Runtime         Agent runtime executes prompt.md, resolves     not in spec
                dependencies, applies integration auth
─────────────────────────────────────────────────────────────
                                ▲ talks to services via
─────────────────────────────────────────────────────────────
Wire protocols  MCP (tool calls) · HTTP/REST · A2A             not in spec
                (agent-to-agent)
─────────────────────────────────────────────────────────────

An agent’s prompt.md replaces what a human would type to give an agent its objective. Skills, MCP servers, and integrations are the resources the agent uses to fulfill that objective. AFPS packages all of these together into a portable, versioned artifact.

Existing standards address different concerns, and AFPS adopts several of them verbatim rather than reinventing them:

These standards are complementary and operate at different layers:

Discovery    MCP Registry / A2A Agent Cards     "where to find agents and tools"
Transport    MCP JSON-RPC / A2A Tasks            "how agents communicate at runtime"
Capability   Agent Skills / MCP Tools            "what an agent knows how to do"
Goal         AFPS Agent                           "what the agent should accomplish"
Packaging    AFPS                                 "how it is all declared and distributed"

1.3 Terminology

1.4 Conformance

The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “NOT RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in BCP 14 [RFC 2119] [RFC 8174] when, and only when, they appear in all capitals, as shown here.

Conforming producers MUST emit manifests and package archives that satisfy the requirements in this document. Conforming consumers MUST reject malformed packages and SHOULD preserve unknown fields when round-tripping manifests. AFPS allows extensibility: manifests and several nested objects accept additional fields unless this specification explicitly forbids them. Extension fields SHOULD follow the _meta mechanism defined in §10.

2. Package Model

2.1 Package Types

AFPS defines four package types:

A package’s type field is the dispatch key used by validators and archive parsers. Producers MUST set it to exactly one of the values above.

Note (migration from AFPS 1.x). AFPS 1.x defined tool and provider package types. AFPS 2.0 removes them: tool is superseded by mcp-server and provider by integration. AFPS 2.0 producers MUST NOT emit tool or provider manifests. Consumers that interoperate with 1.x archives SHOULD read them using the mapping in Appendix D.

2.2 Package Identity

Every AFPS package MUST have a stable AFPS package identity of the form @scope/name. The scope and name segments MUST each match SLUG_PATTERN:

[a-z0-9]([a-z0-9-]*[a-z0-9])?

As a consequence:

The full scoped-name pattern is:

^@[a-z0-9]([a-z0-9-]*[a-z0-9])?\/[a-z0-9]([a-z0-9-]*[a-z0-9])?$

The AFPS package identity is the top-level name field for all four package types. Dependency references (§4) always use this identity.

2.3 Versioning

The top-level version field MUST be a valid semantic version per [SemVer]. Dependency values MUST be valid semantic version ranges.

AFPS itself does not define its own range syntax. It delegates version parsing and range parsing to widely used semantic-version semantics. In practice:

How consumers resolve version ranges against a package catalog is an implementation concern.

2.4 Schema Version Compatibility

AFPS package model evolution is tracked by the schema_version field, a MAJOR.MINOR string. A change in MAJOR indicates a breaking manifest model change; a change in MINOR indicates an additive, backwards-compatible revision. Packages targeting this specification emit schema_version: "2.0".

schema_version applies to all four package types. An mcp-server manifest additionally carries manifest_version, which tags the MCPB-vocabulary version of its embedded server/tools/user_config block (§3.4); the two version fields are independent.

When a consumer encounters a manifest whose schema_version has a higher MAJOR number than the highest version it supports, it MUST reject the manifest and SHOULD report an error identifying the unsupported schema version. Processing a manifest with an unknown major version could lead to silent data loss or incorrect behavior.

When a consumer encounters a manifest whose schema_version has the same MAJOR number but a higher MINOR number than the highest version it supports, it SHOULD process the manifest on a best-effort basis. Unknown fields SHOULD be preserved. Consumers MAY emit a warning indicating that some fields may not be fully understood.

When schema_version is absent from a skill, mcp-server, or integration manifest (where the field is optional), consumers SHOULD treat the package as targeting schema version 2.0. A skill or integration manifest declaring schema_version: "1.0" is a legacy package and SHOULD be read using the mapping in Appendix D.

2.5 Package Archive Format

AFPS packages are distributed as ZIP archives.

Every package archive MUST contain manifest.json at the archive root. Additional required files depend on manifest.type:

Type Required companion content
agent prompt.md at archive root, non-empty
skill SKILL.md at archive root; optional scripts/, references/, assets/ directories (see §3.3)
mcp-server the server payload referenced by server.entry_point; optional icon (see §3.4)
integration optional INTEGRATION.md at archive root

Producers SHOULD use the .afps file extension for package archives (e.g., customer-intake-1.0.0.afps). Consumers MUST accept archives regardless of file extension. The .afps extension is a convention for human recognition and tool association; it does not alter the archive format, which remains standard ZIP.

An mcp-server archive is not, by itself, a strict MCPB bundle: the manifest carries AFPS-native top-level fields (type, schema_version, dependencies, scoped name) alongside the MCPB-vocabulary fields (server, tools, user_config, manifest_version). A producer that wishes to additionally distribute the package to MCPB hosts (such as Claude Desktop) MAY emit a strict-MCPB projection at publish time; the projection rules are out of scope for this revision and reserved for a future minor (§10.2).

All text files in the archive MUST be encoded in UTF-8.

Consumers SHOULD sanitize ZIP entries before processing them. At minimum, entries with path traversal segments (..), absolute paths, null bytes, backslashes, __MACOSX/ prefixes, or directory-only entries SHOULD be ignored.

3. Manifest Specification

All manifests are JSON objects. Unknown top-level fields and unknown nested fields in extensible objects are allowed by the validation model and SHOULD be preserved by tooling unless a tool intentionally normalizes the manifest. Producers SHOULD prefer the _meta extension mechanism (§10) over ad-hoc top-level fields.

3.1 Common Fields

name

version

type

display_name

description

long_description

keywords

license

author

repository

homepage

documentation

support

icon

icons

screenshots

privacy_policies

compatibility

schema_version

dependencies

3.2 Agent Manifest

Agent manifests extend the common fields above. A conforming agent manifest MUST include schema_version, display_name, and author (§3.1). Per-integration runtime configuration (such as requested OAuth scopes) is declared inside the dependency entry under dependencies.integrations (§4.1) using the object form.

Required files

An agent archive MUST contain manifest.json at the archive root and a non-empty prompt.md companion file (§6.1). prompt.md carries the agent’s objective — the instructions sent to the language model. All other agent fields below are manifest fields.

input

output

config

timeout

3.3 Skill Package

AFPS skill packages are a superset of the [Agent Skills] format. A valid Agent Skill directory becomes a valid AFPS skill package when a manifest.json is added alongside the existing SKILL.md. The SKILL.md format and all companion directories defined by Agent Skills are preserved unchanged.

Required files

A skill package MUST contain manifest.json and SKILL.md at the archive root. The manifest MUST validate as a common manifest with type: "skill".

SKILL.md format

SKILL.md SHOULD begin with a YAML frontmatter block followed by a Markdown body containing the skill instructions. For interoperable skill packages:

Consumers SHOULD reject skill packages with a missing frontmatter name. A missing frontmatter description is tolerated but SHOULD be avoided.

The following frontmatter fields are recognized from the Agent Skills specification and SHOULD be preserved by AFPS consumers:

Field Required Description
name SHOULD Skill identifier. Max 64 characters, lowercase alphanumeric and hyphens.
description SHOULD What the skill does and when to use it. Max 1024 characters.
license MAY License name or reference to a bundled license file.
compatibility MAY Environment requirements (intended product, system packages, network access). Max 500 characters.
metadata MAY Arbitrary key-value mapping for additional metadata.
allowed-tools MAY Space-delimited list of pre-approved tools. Experimental in Agent Skills.

AFPS does not extend or modify the frontmatter vocabulary. Additional frontmatter fields defined by future Agent Skills revisions SHOULD be preserved by AFPS consumers.

Optional companion directories

Skill packages MAY include the following directories, as defined by Agent Skills:

Additional files and directories beyond those listed above MAY be included in the archive. Consumers SHOULD preserve them when round-tripping packages.

Progressive disclosure

Skill content is designed for efficient context usage across three levels:

  1. Metadata (~100 tokens): the name and description frontmatter fields, loaded at startup for skill discovery;
  2. Instructions (< 5000 tokens recommended): the full SKILL.md body, loaded when the skill is activated;
  3. Resources (as needed): files in scripts/, references/, assets/, loaded only when required.

Producers SHOULD keep SKILL.md under 500 lines and move detailed reference material to separate files.

3.4 MCP-Server Package

An mcp-server package declares a runnable, local MCP tool server. Its manifest is an AFPS-native manifest at the root (common fields per §3.1, type: "mcp-server", schema_version, name scoped per §2.2, optional dependencies per §4.1) and additionally carries the MCPB (MCP Bundle) field vocabulary for the server run declaration, advisory tool list, and user-configuration mechanism.

AFPS does not redefine these MCPB-vocabulary fields; it adopts them verbatim so that an existing MCPB server payload (the contents of an mcpb init scaffold) can be packaged as an mcp-server without modification. Strict-MCPB host interoperability (validating against the MCPB schema, installing into Claude Desktop or another MCPB host without conversion) is not a goal of AFPS 2.0: a publish-time projection to a strict MCPB bundle MAY be added in a future minor (§10.2). Producers that need strict-MCPB compatibility today MUST emit the strict form separately.

manifest_version

server

tools

user_config

Required files and packaging

An mcp-server archive MUST contain manifest.json at the archive root and the server payload referenced by server.entry_point. A published archive MUST be self-contained: every runtime dependency of the entry point MUST be bundled into the archive. An icon, if present, MUST be a relative path to a real PNG within the archive. The .afps extension is the canonical archive extension (§2.5).

Relationship to MCPB

The server / tools / user_config fields adopt the MCPB vocabulary verbatim so that producers can reuse MCPB tooling and conventions when authoring the server payload. The full AFPS manifest as published is not a strict MCPB manifest (it includes AFPS-native top-level fields outside the MCPB schema) and SHOULD NOT be expected to validate against the MCPB schema or install into an MCPB host as-is. A future minor of AFPS MAY define an interoperability projection that emits a strict-MCPB bundle alongside the AFPS archive.

3.5 Integration Package

An integration package is manifest-only (plus an optional INTEGRATION.md companion). It describes a credentialed binding to an external service: which capability surface the service is reached through (source), how the caller authenticates (auths), how an acquired credential is injected at runtime (delivery), and optional per-tool metadata. The full authentication model is specified in §7.

An integration is service-centric: the service (for example Gmail, Stripe) is the identity, and the capability source is one way to reach it. Authentication is bound to the integration, not to the source. An integration is an AFPS-native manifest; it is never an MCPB manifest and is not installed directly into an MCPB host. When an integration’s source.kind is local, it references an mcp-server package (§7.1); the integration’s authentication layer is applied by the AFPS runtime on top of that server.

Common fields

An integration manifest uses the common fields (§3.1): name (scoped), version, type: "integration", schema_version, display_name, and any of the optional common fields — description, long_description, keywords, license, author, homepage, documentation, support, repository, icon, icons, screenshots, privacy_policies, compatibility, dependencies, _meta. No common field is excluded for integrations; the integration-specific fields (source, auths, …) are added on top.

source

auths

The integration manifest uses the common-fields icon / icons (§3.1) for presentation; the legacy integration-scoped icon field is folded into the common fields and is no longer documented separately here.

INTEGRATION.md

4. Dependency Model

4.1 Dependency Declaration

A package declares its dependencies using the dependencies field. The field contains optional maps keyed by dependency type:

{
  "dependencies": {
    "integrations": {
      "@acme/gmail": {
        "version": "^1.0.0",
        "scopes": ["https://www.googleapis.com/auth/gmail.readonly"]
      }
    },
    "skills": { "@acme/rewrite-tone": "^1.0.0" },
    "mcp_servers": { "@acme/fetch-json": "^1.0.0" }
  }
}

Each map entry is an AFPS package identity (§2.2) paired with a dependency value. Dependency keys MUST be valid scoped names matching the pattern defined in §2.2. All package types MAY declare a top-level dependencies field.

A dependency value takes one of two shapes:

Consumers MUST accept both forms and normalize the string form to { "version": "<string>" } before processing.

Per-dependency-type fields

For dependencies.integrations.<id> (object form), AFPS v2.0 defines the following OPTIONAL fields:

For dependencies.skills.<id> and dependencies.mcp_servers.<id>, AFPS v2.0 defines no extra fields beyond version. Producers MAY add fields under _meta within the object form (§10).

Migration note. AFPS earlier drafts declared per-integration configuration under a sibling agent-level field integrations_configuration ({ scopes }). That field is deprecated in AFPS 2.0 in favor of the object dependency form above. Consumers MUST keep accepting an agent-level integrations_configuration map for backward compatibility and MUST merge it into the dependency entries (a sibling scopes always wins over the deprecated map).

The following diagram illustrates how an agent composes its dependencies:

                  ┌────────────────────────────────┐
                  │  @acme/customer-intake         │
                  │  type: agent                   │
                  │  prompt.md (objective)         │
                  └──────┬─────────────────────────┘
                         │ dependencies
          ┌──────────────┼──────────────┐
          ▼              ▼              ▼
  ┌──────────────┐ ┌────────────┐ ┌────────────┐
  │ @acme/gmail  │ │ @acme/     │ │ @acme/     │
  │ integration  │ │ rewrite-   │ │ fetch-json │
  │ (OAuth2)     │ │ tone       │ │ mcp-server │
  │              │ │ skill      │ │            │
  └──────────────┘ └────────────┘ └────────────┘

4.2 Version Range Resolution

A dependency entry’s version (in the object form, or the entry value itself in the string form) MUST be a valid semver range (e.g., ^1.0.0, ~2.1, >=3.0.0, *). Consumers MUST reject invalid semver range syntax. How consumers resolve ranges against a package catalog is an implementation concern.

4.3 Circular Dependencies

A package MUST NOT declare a dependency on itself. Consumers SHOULD detect circular dependencies in the transitive dependency graph and report them with a concrete cycle path.

4.4 Integration Configuration (Deprecated)

The sibling integrations_configuration map keyed by integration package id is deprecated in AFPS 2.0. Per-integration configuration (such as requested OAuth scopes or auth-method selection) is now declared inline inside dependencies.integrations.<id> using the object dependency form (§4.1).

Consumers MUST keep accepting the deprecated integrations_configuration map for backward compatibility and MUST merge it into the dependency entries at load time. The merge is per-field: any field present in the dependency-entry object form (scopes, auth_key, etc.) takes precedence over the same field in the deprecated map; fields only present in the deprecated map are carried through as if they had been declared in the dependency entry. The deprecated map is otherwise opaque to consumers.

5. Schema System

AFPS uses standard JSON Schema 2020-12 for property definitions within agent input, output, and config sections, and within an integration auth method’s credentials.schema (§7.5). The container schema MUST be an object with type: "object" and a properties record. Any valid JSON Schema 2020-12 keyword may be used within property definitions.

5.1 JSON Schema Properties

All property definitions within an AFPS schema MUST be valid JSON Schema 2020-12. The full JSON Schema vocabulary is supported, including composition keywords (allOf, anyOf, oneOf, not), conditional keywords (if/then/else), references ($ref, $defs), and all type-specific keywords.

The following keywords are commonly used in AFPS schemas:

Keyword Type Required Description
type string MAY Declares the field kind (string, number, integer, boolean, array, object).
description string MAY Human-facing explanation of the field.
default any MAY Suggested default value.
enum array MAY Enumerated allowed values.
format string MAY Formatting hint (date-time, email, uri, etc.).
contentMediaType string MAY IANA media type (RFC 2046). Used with format: "uri" to indicate file fields (see §5.2).
items object MAY Describes array items (when type is array).
maxItems integer MAY Maximum number of array items.

JSON Schema keywords such as contentMediaType and maxItems are part of the JSON Schema 2020-12 vocabulary and retain their standard (camelCase) spelling. The AFPS snake_case convention applies to AFPS-defined manifest fields, not to embedded JSON Schema documents.

This is not an exhaustive list. Any keyword defined by JSON Schema 2020-12 is valid within property definitions.

5.2 File Field Convention

AFPS represents file upload fields using standard JSON Schema types rather than a custom file type. A consumer detects a file field by the combination of format: "uri" and the presence of contentMediaType.

Single file:

{
  "type": "string",
  "format": "uri",
  "contentMediaType": "application/octet-stream",
  "description": "Upload a document"
}

Multiple files:

{
  "type": "array",
  "items": {
    "type": "string",
    "format": "uri",
    "contentMediaType": "application/octet-stream"
  },
  "maxItems": 5,
  "description": "Upload supporting documents"
}

At runtime, the field value is a URI reference to the uploaded file. The contentMediaType value MAY be application/octet-stream (any file type) or a more specific media type such as application/pdf.

The URI scheme is consumer-defined. A consumer MAY use http(s):// for direct references, data: for inline content, or a private scheme (for example upload://upl_xxx) to denote a pre-uploaded blob managed by the consumer. Consumers MUST resolve the URI to the actual file bytes before passing the value to an agent at run time.

Upload constraints such as accepted file extensions and maximum file size are not JSON Schema concerns. They are declared in the file_constraints section of the schema wrapper (see §5.4).

5.3 Schema Object Structure

An AFPS schema container MUST have:

It MAY also contain:

Property definitions support the full JSON Schema 2020-12 vocabulary, including composition (allOf, anyOf, oneOf), conditionals (if/then/else), and references ($ref, $defs). The schema validator validates property definitions against the official JSON Schema 2020-12 meta-schema.

5.4 Input, Output, and Config Schemas

input, output, and config all use a wrapper shape containing a required schema member and optional AFPS metadata:

{
  "schema": {
    "type": "object",
    "properties": {}
  },
  "file_constraints": {},
  "ui_hints": {},
  "property_order": []
}

The schema member MUST be a valid JSON Schema 2020-12 object. The remaining fields are AFPS-specific metadata that lives outside the schema to preserve JSON Schema purity.

The wrapper object is required when any of these sections are present. A bare schema object is not valid in those locations.

file_constraints

ui_hints

property_order

Although the three sections share the same structural format, they have distinct semantics and lifecycles:

Section Lifecycle Timing Description
input Per-run Supplied each time the agent runs Data the user provides for a specific run (e.g., a search query, a file to process).
output Per-run Produced at the end of each run Structured result the agent returns (e.g., a summary, a report).
config Per-deployment Set once during setup, reused across runs Settings that remain constant across runs (e.g., preferred language, notification threshold).

A consumer SHOULD prompt for input values at each run and SHOULD persist config values so they do not need to be re-entered.

6. Execution Model

6.1 Execution Context

An agent package MUST include a non-empty prompt.md companion file. That file contains the primary instructions for the agent.

An agent execution is non-interactive and run-to-completion: the agent receives the full execution context, processes the task autonomously, and returns a structured result. There is no conversational back-and-forth — the agent runs from start to finish without user interaction.

A consumer MAY construct an execution context from:

AFPS does not define prompt templating, state persistence, scheduling, or transport semantics. Those concerns are out of scope.

6.2 Timeout

timeout is a numeric hint expressed in seconds. It communicates the producer’s expectation of how long the agent needs to complete.

AFPS v2.0 does not impose a manifest-level default for this field. If a consumer chooses a local default, it SHOULD document it separately from the manifest itself.

7. Integration Authentication

This section specifies the integration manifest model: its capability source, authentication methods, credential delivery, and declarative credential acquisition.

An integration authenticates the upstream-credential hop — the credential the integration’s source needs to reach the external service. This is distinct from, and complementary to, the client-to-server authorization an MCP host performs (which the MCP Authorization specification covers): AFPS describes the upstream hop that MCP declares out of scope.

7.1 Capability Source

source declares the surface the integration binds to. It is an object with a kind discriminant and exactly one matching sub-object.

"source": {
  "kind": "local" | "remote" | "api",

  // kind = local: reference an mcp-server by AFPS identity + semver range (§2.2, §4).
  "server": { "name": "@example/gmail-server", "version": "^1.2.0", "vendored": true },

  // kind = remote: a hosted MCP endpoint.
  "remote": { "url": "https://example.com/mcp", "transport": "streamable-http" | "sse" },

  // kind = api: a credential-injecting HTTP API surface (no MCP server).
  "api": { "upload_protocols": ["google-resumable", "s3-multipart", "tus", "ms-resumable"] }
}

A source whose surface is not a local MCP server (remote, or any non-local API) cannot be expressed as an mcp-server package and has no .mcpb form. This is a property of the source kind, not a runnability gradient.

7.2 Auth Methods

auths is a map of one or more named authentication methods. The key matches ^[a-z][a-z0-9_]*$ and disambiguates methods when a manifest declares more than one. Each value is an object whose type selects the authentication model:

Every auth method MUST declare delivery (§7.6) — where its credential is injected at runtime. An auth method MAY declare authorized_uris / allow_all_uris (§7.9).

7.3 OAuth2 Configuration and Discovery

For an auth method of type: "oauth2", the endpoint set is resolved discovery-first: a consumer SHOULD fetch the authorization server’s metadata document and MAY accept manual overrides. Discovery is best-effort enrichment, never a precondition — many providers publish no discovery document, so every discovered field MUST be overridable and a fully-manual configuration MUST be supported.

issuer

Endpoint fields (RFC 8414 / OIDC Discovery vocabulary, verbatim)

These fields use the snake_case field names defined by [RFC 8414] and [OpenID Connect Discovery] so that a value may be copied directly from a discovery document. Any field a consumer obtains from discovery MUST be overridable by an explicit manifest value.

Discovery procedure

When issuer is present and a consumer performs discovery, it MUST probe the three well-known locations, in order, until one returns a valid document whose issuer member equals the requested issuer (after stripping any trailing /):

  1. RFC 8414 path-insertion: https://{host}/.well-known/oauth-authorization-server{/path};
  2. OIDC path-insertion: https://{host}/.well-known/openid-configuration{/path};
  3. OIDC path-append: https://{host}{/path}/.well-known/openid-configuration.

A consumer MUST validate that the returned issuer equals the configured issuer before using any discovered endpoint. Discovery failure MUST fall back to the manual endpoint fields; it MUST NOT block configuration when those fields are present. See §8.7 for the SSRF considerations of fetching discovery documents.

7.4 Scopes

OAuth scopes are declared in two AFPS fields, distinct from the non-authoritative scopes_supported of [RFC 8414]:

default_scopes

scope_catalog

Identity claims

7.5 Credential Schema

For auth methods of type api_key, basic, mtls, or custom, credentials.schema is REQUIRED. It declares the shape of the user-supplied credential bag. For mtls, the schema SHOULD describe the client certificate (PEM), the private key (PEM), and an optional intermediate chain.

7.6 Credential Delivery

delivery declares where an acquired credential is injected at runtime. At least one of {http, env, files} MUST be declared per auth method.

The block below is a syntax catalogue showing all three delivery shapes; it is NOT a valid single delivery object. http is mutually exclusive with env/files (see the rule after this block), so a real auth method declares either http alone, or any combination of env and files.

"delivery": {
  // HTTP injection. `in` + `name` adopt the OpenAPI Security Scheme location vocabulary;
  // `prefix`, `value`, and `encoding` are AFPS additions.
  "http": {
    "in": "header" | "query" | "cookie",
    "name": "Authorization",
    "prefix": "Bearer ",                       // OAuth/bearer: no encoding
    "value": "{$credential.access_token}",
    "allow_server_override": false
  },
  // HTTP Basic vendor pattern (RFC 7617): base64 over the rendered `value` only;
  // the `Basic ` prefix is concatenated AFTER encoding (the scheme prefix is not base64'd).
  // "http": { "in": "header", "name": "Authorization", "prefix": "Basic ",
  //           "value": "{$credential.email}/token:{$credential.api_key}",
  //           "encoding": "base64" },
  // Environment-variable injection (Kubernetes-style vocabulary).
  "env": {
    "GMAIL_TOKEN": {
      "value": "{$credential.access_token}",
      "sensitive": true,
      "user_config_key": "GMAIL_TOKEN"
    }
  },
  // File injection (Kubernetes-style vocabulary). `mode` is an octal string; default "0400".
  "files": {
    "/run/creds/token": { "value": "{$credential.token}", "mode": "0400" }
  }
}

http (proxy injection, server never holds the secret) and env/files (server holds the secret) are mutually exclusive per auth method: an auth method MUST NOT mix http with env/files.

No specification standardizes runtime secret injection into environment variables and files; the env/files vocabulary borrows Kubernetes naming (mode, mount-style paths) and is an AFPS contribution.

Value templates use the runtime-expression grammar of §7.7 ({$credential.<field>}, {$outputs.<name>}).

7.7 Declarative Credential Acquisition (connect)

connect declares how a custom auth method acquires its credential without OAuth. It is valid only for type: "custom". A connect object MUST contain exactly one of:

"connect": {
  "login": {
    // Inline HTTP request. (AFPS divergence from Arazzo, which references an OpenAPI
    // operation; an integration has no OpenAPI document to point at, so the request is inline.)
    "request": {
      "method": "POST",
      "url": "https://api.example.com/login",
      "headers": {},
      "body": "…",
      "content_type": "application/json"
    },
    // Arazzo Criterion vocabulary (condition + optional context + type). When omitted,
    // success defaults to HTTP 2xx (AFPS-defined; Arazzo leaves HTTP success undefined).
    "success_criteria": [ { "condition": "$statusCode == 200" } ],
    // Outputs: each value is an Arazzo runtime-expression string, an Arazzo
    // Selector Object, OR an AFPS extractor object for cases Arazzo cannot
    // express (cookie, jwt).
    "outputs": {
      "token": "$response.body#/access_token",
      "exp":   "$response.header.X-Expires-After",
      "user":  { "context": "$response.body", "selector": "$.profile.id", "type": "jsonpath" },
      "csrf":  { "from": "cookie", "name": "XSRF-TOKEN" },
      "sub":   { "from": "jwt", "token": "{$outputs.token}", "path": "/sub" }
    },
    "expires_in_output": "exp",
    "identity_outputs": ["sub"]
  },
  "limits": { "request_timeout_ms": 30000, "max_response_bytes": 5000000 }
}

Gating rule. A delivery.* value template MAY only reference declared connect outputs (or, for the orchestrated tool mode, its declared produces). A delivery referencing a non-output — for example a bootstrap login secret — is a manifest error.

Runtime expressions are embedded into templates with {$expr} (for example {$outputs.token}). The grammar is adopted from [Arazzo]; the extractor objects (from: jwt|regex|cookie) are AFPS extensions.

7.8 Per-Tool Policy

integration.tools_policy is an OPTIONAL sparse policy table keyed by tool name. It carries per-tool authorization metadata for local and remote sources. It is NOT the catalog of “tools this integration exposes” — that catalog is canonical to the referenced surface (the disambiguating reason for the _policy suffix, distinct from mcp-server.tools which IS such a catalog):

When integration.tools_policy.<name> is declared, it augments the canonical entry for <name>. Consumers SHOULD validate at install (or at publish, for a registry) that each key in integration.tools_policy corresponds to a tool present in the resolved canonical catalog.

"tools_policy": {
  "list_issues": {
    "required_scopes": ["repo"],
    "required_auth_key": "oauth",
    "url_patterns": [ { "pattern": "https://api.github.com/**", "methods": ["GET"] } ]
  }
}

hidden_tools

integration.hidden_tools is an OPTIONAL array of tool names. Tools listed here exist in the resolved canonical catalog but MUST NOT be exposed to the agent’s tool picker / tools/list surface. Tools referenced by a connect.tool (run-start primitives) are auto-hidden, so hidden_tools only needs to enumerate the remaining tool names to suppress.

Note (placement). Per-tool policy lives on the integration because the policy itself (required scopes, allowed URL patterns, auth-key selection) is a property of how the credentialed binding is used, not of the server’s tool list.

7.9 URI Restrictions

An auth method MAY restrict which upstream URIs the integration may send credentials to:

Consumers MUST NOT send credentials to URIs outside the authorized set unless allow_all_uris is explicitly true, and SHOULD treat allow_all_uris: true as security-sensitive (§8.6).

7.10 Setup Guide

An integration MAY declare a setup_guide with human-facing instructions for configuring credentials (for example, registering an OAuth client):

callback_url_hint is a property of an OAuth2 auth method (not of the integration as a whole), and is therefore declared under auths.<key>.callback_url_hint (string; often containing a placeholder such as ``). The top-level setup_guide.callback_url_hint from earlier drafts is deprecated; consumers MUST keep accepting it for backward compatibility and SHOULD treat it as a fallback when the auth method does not declare one.

7.11 OpenAPI Security Scheme Mapping (Informative)

An AFPS auth method maps onto an [OpenAPI] Security Scheme (also used by [A2A] securitySchemes and the [OpenAI Apps SDK]). Consumers MAY use this mapping to expose AFPS integrations to A2A clients, Apps SDK hosts, or other OpenAPI-aware tooling. Conversely, an integration manifest MAY be derived (in part) from a published OpenAPI Security Scheme.

AFPS auths.<key>.type OpenAPI Security Scheme
oauth2 { "type": "oauth2", "flows": { ... } } — flows derived from authorization_endpoint/token_endpoint/default_scopes/scope_catalog
api_key { "type": "apiKey", "in": "<delivery.http.in>", "name": "<delivery.http.name>" } — when delivery.http is declared
basic { "type": "http", "scheme": "basic" }
mtls { "type": "mutualTLS" } (OpenAPI 3.1+)
custom not standardly representable; SHOULD be omitted from a derived OpenAPI document or recorded under _meta (§10)

This mapping is informative and does not impose normative requirements on AFPS consumers.

8. Security Considerations

AFPS packages describe AI workflows that may access external services, process user data, and execute code. Implementers MUST consider the following threats.

8.1 Archive Processing

ZIP archives are a well-known vector for path traversal and denial-of-service attacks. Consumers MUST:

Consumers SHOULD ignore __MACOSX/ directories and other platform-specific metadata entries.

8.2 MCP-Server Code Execution

MCP-server packages (§3.4) bundle a runnable server payload that consumers and MCPB hosts load and execute. This is the highest-risk surface in the AFPS model:

AFPS does not define how server code is loaded or executed beyond delegating to MCPB. Consumers are responsible for implementing appropriate security measures for their execution environment.

8.3 Credential Handling

Integration packages (§3.5, §7) describe authentication configurations that involve OAuth tokens, API keys, and other secrets:

8.4 Prompt Injection

Agent packages include a prompt.md companion file whose content is typically sent to a language model. Malicious or compromised packages can embed prompt injection attacks:

8.5 Supply Chain

Packages distributed through registries are subject to supply chain attacks including typosquatting, dependency confusion, and malicious updates:

8.6 URI Restrictions

Integration auth methods include authorized_uris to restrict which upstream endpoints a credential can be sent to:

8.7 Credential Discovery (SSRF)

OAuth discovery (§7.3) and credential schemas (§7.5) involve fetching or resolving URIs that may be influenced by package content:

9. Privacy Considerations

AFPS packages may process personally identifiable information (PII) through agent inputs, integration connections, and execution outputs:

Implementers operating in jurisdictions with data protection regulations (e.g., GDPR, CCPA) SHOULD consult their compliance requirements for the handling of user data within AI workflows.

10. Extensibility

AFPS manifests and several nested objects accept additional fields beyond those defined in this specification. This design allows producers and consumers to experiment with new metadata without requiring a specification revision.

10.1 The _meta Extension Mechanism

AFPS adopts the Model Context Protocol _meta key convention as its single extension mechanism, across all package types. Extension data MUST be placed inside a top-level _meta object (and SHOULD NOT appear as ad-hoc top-level fields):

{
  "name": "@example/my-agent",
  "version": "1.0.0",
  "type": "agent",
  "schema_version": "2.0",
  "_meta": {
    "dev.afps/policy": { "tier": "high" },
    "dev.appstrate/cost-center": "engineering"
  }
}

The _meta object is a record of namespaced keys. Each key is an OPTIONAL reverse-DNS prefix (a dotted label sequence followed by /) plus a name; for example dev.afps/policy or dev.appstrate/cost-center. The value at a namespaced key MUST be a JSON object.

Editorial note (namespace control). The afps.dev domain corresponding to the dev.afps/ prefix is under active registration by the AFPS maintainers. Implementations published before the domain is operationally controlled SHOULD additionally accept the transitional prefix dev.appstrate.afps/ (which is unambiguously vendor-controlled) and treat it as an alias of dev.afps/. Once the domain is controlled, this alias will be deprecated.

This convention:

Consumers MUST NOT reject manifests that contain unknown _meta keys, and MUST NOT fail on _meta values they do not understand. Consumers MAY ignore extension data they do not understand and SHOULD preserve it when round-tripping manifests.

10.2 Future Standard Fields

When an extension carried under _meta gains broad adoption across multiple implementations, it MAY be promoted to a standard field in a future specification revision. Upon promotion, the standard field name becomes normative and the _meta entry becomes deprecated.

11. References

Normative References

Informative References


Appendices

Appendix A. Field Reference Table

Field Context Type Requirement Constraints / Notes Default
name all manifests string MUST scoped name @scope/name (§2.2) none
version all manifests string MUST valid semver version none
type all manifests string MUST agent\|skill\|mcp-server\|integration none
display_name all manifests string MUST for agent; SHOULD for skill, mcp-server, integration agent value min length 1 none
description all manifests string MAY free text none
long_description all manifests string MAY Markdown long-form description none
keywords all manifests string[] MAY arbitrary strings none
license all manifests string MAY SPDX identifier RECOMMENDED none
author all manifests string | object MUST for agent; MAY for others string form, or { name (REQUIRED), email?, url? } (npm-aligned) none
repository all manifests string | object MAY URI string, or { type, url, directory? } (npm-aligned) none
homepage all manifests string MAY URI; package homepage none
documentation all manifests string MAY URI; documentation page none
support all manifests string MAY URI; support/issues none
icon all manifests string MAY relative archive path to a PNG, or a URI none
icons all manifests object[] MAY [{ src, size?, theme? }] none
screenshots all manifests string[] MAY image paths/URIs none
privacy_policies all manifests string[] MAY privacy-policy URIs none
compatibility all manifests object MAY { platforms?, runtimes?, clients? } none
schema_version all manifests string MUST for agent; MAY for skill, mcp-server, integration MAJOR.MINOR; producers MUST emit 2.0 none
dependencies all manifests object MAY optional dependency maps (§4.1) none
dependencies.skills all manifests map MAY keys scoped names; values semver range string or { version, ... } (§4.1) none
dependencies.mcp_servers all manifests map MAY keys scoped names; values semver range string or { version, ... } (§4.1) none
dependencies.integrations all manifests map MAY keys scoped names; values semver range string or { version, scopes?, auth_key? } (§4.1) none
dependencies.integrations.<id>.scopes all manifests string[] MAY requested OAuth scopes for the integration (§7.4) none
dependencies.integrations.<id>.auth_key all manifests string MAY selects an auths.<key> entry on the integration none
integrations_configuration agent map MAY (deprecated) superseded by dependencies.integrations.<id> object form (§4.4); kept for backward compatibility none
input agent object MAY per-run data; requires schema child none
input.schema agent object MUST if input present AFPS schema object none
output agent object MAY per-run result; requires schema child none
output.schema agent object MUST if output present AFPS schema object none
config agent object MAY per-deployment settings; requires schema child none
config.schema agent object MUST if config present AFPS schema object none
file_constraints agent schema wrapper object MAY keyed by property name; accept, max_size none
ui_hints agent schema wrapper object MAY keyed by property name; placeholder none
property_order agent schema wrapper string[] MAY presentation order hint none
timeout agent number MAY timeout hint in seconds none
prompt.md agent archive file MUST non-empty companion file at archive root; the agent’s objective (§6.1) none
manifest_version mcp-server string MUST tags the MCPB-vocabulary version of server/tools/user_config; 0.3 baseline, 0.4 for uv none
server mcp-server object MUST run declaration (type, entry_point, mcp_config); MCPB vocabulary none
server.type mcp-server string MUST node\|python\|binary (manifest_version=0.3); uv (0.4) none
server.entry_point mcp-server string MUST relative path within the archive to the server entry point; MCPB vocabulary none
server.mcp_config mcp-server object MUST { command, args?, env?, platform_overrides? }; MCPB vocabulary none
tools mcp-server array MAY advisory tool list ({ name, description }); MCPB vocabulary none
user_config mcp-server object MAY user configuration; sensitive: true for secrets; MCPB vocabulary none
source integration object MUST kindlocal\|remote\|api plus matching sub-object none
source.server integration object MUST for kind=local { name (scoped), version (range), vendored? } none
source.server.name integration string MUST for kind=local scoped name of the referenced mcp-server (§2.2) none
source.server.version integration string MUST for kind=local semver range for the referenced mcp-server none
source.server.vendored integration boolean MAY records that the server payload is bundled MCPB-style false
source.remote integration object MUST for kind=remote { url, transport: streamable-http\|sse } none
source.remote.url integration string MUST for kind=remote URI of the hosted MCP endpoint none
source.remote.transport integration string MUST for kind=remote streamable-http\|sse none
source.api integration object MUST for kind=api { upload_protocols?: open string array } none
source.api.upload_protocols integration string[] MAY open array; reserved values: google-resumable, s3-multipart, tus, ms-resumable. Custom protocols SHOULD use a reverse-DNS prefix none
auths integration object MUST map keyed by ^[a-z][a-z0-9_]*$; ≥1 entry none
auths.<key>.type integration string MUST oauth2\|api_key\|basic\|mtls\|custom none
auths.<key>.issuer integration string SHOULD for oauth2 OAuth/OIDC issuer; enables discovery none
auths.<key>.authorization_endpoint integration string MUST for oauth2 w/o discovery RFC 8414 none
auths.<key>.token_endpoint integration string MUST for oauth2 w/o discovery RFC 8414 none
auths.<key>.userinfo_endpoint integration string MAY OIDC Discovery none
auths.<key>.token_endpoint_auth_method integration string MAY RFC 7591 / OIDC Core values; client_secret_basic default (RFC 8414 §2, RFC 7591 §2) none
auths.<key>.code_challenge_methods_supported integration string[] MAY PKCE methods, e.g. ["S256"] (RFC 8414 / RFC 7636) none
auths.<key>.resource integration string MAY RFC 8707 resource indicator (not audience) none
auths.<key>.authorization_params integration object MAY extra authorize query params (AFPS) none
auths.<key>.default_scopes integration string[] MAY baseline requested scopes none
auths.<key>.scope_catalog integration object[] MAY { value, label, description?, implies? } (AFPS authoritative) none
auths.<key>.identity_claims integration object MAY AFPS key → OIDC claim name none
auths.<key>.required_identity_claims integration string[] MAY required OIDC claims none
auths.<key>.credentials.schema integration object MUST for api_key/basic/mtls/custom self-contained JSON Schema 2020-12; local $ref only none
auths.<key>.delivery integration object MUST ≥1 of http, env, files; http exclusive of env/files none
auths.<key>.delivery.http integration object MAY { in, name, prefix?, value, encoding?, allow_server_override? } none
auths.<key>.delivery.http.in integration string MUST if http present header\|query\|cookie (OpenAPI) none
auths.<key>.delivery.http.name integration string MUST if http present header/query/cookie parameter name (OpenAPI) none
auths.<key>.delivery.http.value integration string MUST if http present value template ({$credential.*}, {$outputs.*}) none
auths.<key>.delivery.http.prefix integration string MAY literal prefix prepended to the rendered value (e.g. "Bearer ") none
auths.<key>.delivery.http.encoding integration string MAY base64 (RFC 4648 §4), applied to value only none
auths.<key>.delivery.http.allow_server_override integration boolean MAY whether the source server may override the injected value false
auths.<key>.delivery.env integration object MAY map of VAR{ value, sensitive?, user_config_key? }; maps to MCPB user_config none
auths.<key>.delivery.env.<var>.value integration string MUST if entry present value template for the environment variable none
auths.<key>.delivery.env.<var>.sensitive integration boolean MAY marks the value secret (aligns with MCPB user_config sensitive) false
auths.<key>.delivery.env.<var>.user_config_key integration string MAY MCPB user_config key for local-source binding; defaults to the env-variable name none
auths.<key>.delivery.files.<path>.value integration string MUST if entry present value template for the file contents none
auths.<key>.delivery.files.<path>.mode integration string MAY octal string (e.g. "0400") "0400"
auths.<key>.callback_url_hint integration string MAY OAuth-client registration callback hint (often containing ``) none
auths.<key>.delivery.files integration object MAY map of path → { value, mode? }; mode octal string mode "0400"
auths.<key>.connect integration object MAY (custom only) exactly one of login / tool; optional limits none
auths.<key>.connect.login.request integration object MUST if login present inline HTTP request { method, url, headers?, body?, content_type? } none
auths.<key>.connect.login.success_criteria integration object[] MAY Arazzo Criterion; default HTTP 2xx HTTP 2xx
auths.<key>.connect.login.outputs integration object MAY Arazzo runtime-expression string, Arazzo Selector Object {context,selector,type}, or AFPS extractor (cookie/jwt/regex) none
auths.<key>.connect.login.expires_in_output integration string MAY name of the output carrying credential expiry none
auths.<key>.connect.login.identity_outputs integration string[] MAY names of outputs that establish the connection identity none
auths.<key>.connect.tool integration object MAY (custom only) experimental alternative to login; tools used are auto-hidden (hidden_tools) none
auths.<key>.connect.limits integration object MAY { request_timeout_ms?, max_response_bytes? } (positive numbers) none
auths.<key>.authorized_uris integration string[] MAY allowed upstream URI patterns (glob) none
auths.<key>.allow_all_uris integration boolean MAY unrestricted upstream access false
tools_policy integration object MAY sparse per-tool policy table (augments canonical tool catalog of the referenced source); keys MUST resolve in the canonical catalog none
tools_policy.<name>.required_scopes integration string[] MAY scopes a tool requires none
tools_policy.<name>.required_auth_key integration string MAY selects an auths entry none
tools_policy.<name>.url_patterns integration object[] MAY { pattern (glob), methods? } none
hidden_tools integration string[] MAY tool names suppressed from the agent’s surface; tools used as connect.tool are auto-hidden none
setup_guide integration object MAY setup metadata none
setup_guide.callback_url_hint integration string MAY (deprecated) superseded by auths.<key>.callback_url_hint; kept for backward compatibility none
setup_guide.steps integration object[] MAY ordered setup steps none
setup_guide.steps[].label integration string MUST if step present non-empty recommended none
setup_guide.steps[].url integration string MAY URI recommended none
INTEGRATION.md integration archive file MAY optional API documentation for agent consumption none
SKILL.md frontmatter name skill content string SHOULD max 64 chars, lowercase alphanumeric and hyphens none
SKILL.md frontmatter description skill content string SHOULD max 1024 chars; missing value warns none
SKILL.md frontmatter license skill content string MAY license name or file reference none
SKILL.md frontmatter compatibility skill content string MAY max 500 chars; environment requirements none
SKILL.md frontmatter metadata skill content map MAY arbitrary string key-value pairs none
SKILL.md frontmatter allowed-tools skill content string MAY space-delimited tool list; experimental none
scripts/ skill archive directory MAY executable code for agents none
references/ skill archive directory MAY additional documentation none
assets/ skill archive directory MAY static resources, templates none
_meta any manifest or extensible nested object object MAY reverse-DNS namespaced extension data (§10); permitted on the root manifest and on any nested object the spec does not explicitly close none

Appendix B. Regex Patterns

SLUG_PATTERN         = [a-z0-9]([a-z0-9-]*[a-z0-9])?
SLUG_REGEX           = ^[a-z0-9]([a-z0-9-]*[a-z0-9])?$
SCOPED_NAME_REGEX    = ^@[a-z0-9]([a-z0-9-]*[a-z0-9])?\/[a-z0-9]([a-z0-9-]*[a-z0-9])?$
SCHEMA_VERSION_REGEX = ^(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)$
AUTH_KEY_REGEX       = ^[a-z][a-z0-9_]*$
META_NAMESPACE_KEY   = ^([a-z0-9-]+(\.[a-z0-9-]+)+\/)?[A-Za-z0-9._-]+$

Semantic-version and range validation are delegated to semver parsing functions rather than regexes.

Appendix C. Default Values

AFPS v2.0 validation does not inject manifest defaults. Omitted optional fields remain omitted.

Common consumer-side defaults observed in interoperable implementations include:

Field Resolved default Notes
auths.<key>.token_endpoint_auth_method client_secret_basic OAuth2 token request authentication; matches RFC 8414 §2 / RFC 7591 §2 default
auths.<key>.allow_all_uris false resolved integration auth method
auths.<key>.delivery.files.<path>.mode 0400 octal string
auths.<key>.connect.login.success_criteria HTTP 2xx when omitted
manifest_version 0.3 mcp-server MCPB baseline
schema_version 2.0 common consumer default for new agents/integrations
timeout 300 common consumer default for new agents

These defaults are non-normative unless a producer explicitly writes them into the manifest.

Appendix D. Migration from AFPS 1.x

AFPS 1.x defined two package types — tool and provider — and a camelCase field vocabulary. AFPS 2.0 removes both types and adopts snake_case. AFPS 2.0 producers MUST NOT emit tool or provider manifests, and MUST emit snake_case field names. Consumers that interoperate with 1.x archives SHOULD read them using the mappings below.

Type mapping

AFPS 1.x type AFPS 2.0 type Notes
tool mcp-server A 1.x tool (single entrypoint + tool interface object) is reframed as a runnable MCP server. The tool.name/tool.description become an entry in the MCPB tools array; the entrypoint and runtime become the MCPB server declaration.
provider integration A 1.x provider (definition.authMode + auth sub-object) becomes an integration with a source and an auths map.

Field mapping (camelCase → snake_case)

AFPS 1.x field AFPS 2.0 field
displayName display_name
schemaVersion schema_version
providersConfiguration dependencies.integrations.<id> object form (§4.1); integrations_configuration accepted for backward compatibility
dependencies.providers dependencies.integrations
dependencies.tools dependencies.mcp_servers
tool.inputSchema (server tools advertise no input schema in MCPB; obtained from the running server)
fileConstraints / maxSize file_constraints / max_size
uiHints ui_hints
propertyOrder property_order
iconUrl icon
definition.authMode auths.<key>.type
definition.oauth2.authorizationUrl auths.<key>.authorization_endpoint (RFC 8414)
definition.oauth2.tokenUrl auths.<key>.token_endpoint (RFC 8414)
definition.oauth2.tokenAuthMethod auths.<key>.token_endpoint_auth_method
definition.credentials.schema auths.<key>.credentials.schema
definition.credentialTransform auths.<key>.delivery.http with value template + encoding: "base64"
definition.authorizedUris auths.<key>.authorized_uris
definition.allowAllUris auths.<key>.allow_all_uris
definition.availableScopes auths.<key>.scope_catalog
definition.uploadProtocols source.api.upload_protocols
setupGuide.callbackUrlHint auths.<key>.callback_url_hint (preferred); setup_guide.callback_url_hint accepted as a deprecated fallback
extension fields (x-*) _meta reverse-DNS keys (§10)

The 1.x OAuth1 auth mode (definition.oauth1) has no AFPS 2.0 equivalent in the core vocabulary; an integration requiring OAuth1 SHOULD model it as a custom auth method with a connect flow (§7.7) or carry it under _meta.

New common fields (AFPS 1.x → 2.0)

The following common fields were added in AFPS 2.0 and are aligned with MCPB. They have no AFPS 1.x equivalent; producers MAY emit them when migrating, consumers MUST tolerate their absence in legacy manifests:

long_description, homepage, documentation, support, icons (array form), screenshots, privacy_policies, compatibility (structured form).

author and repository now accept either a string (1.x-compatible) or a structured object (MCPB/npm-aligned). The legacy integration-level icon field is folded into the common-fields icon and icons (§3.1).

Appendix E. Origins

This specification was initially drafted by Appstrate and published as an independent open standard. The normative content of this specification (§1–§10) defines the standard independently of any specific implementation. Conforming implementations MAY use different internal structures, validation strategies, or execution models while maintaining specification compliance.

See IMPLEMENTATIONS.md for known implementations.