n2ns / laravel-post2site
Laravel backend package for the N2N Post2Site Content Publishing API Contract.
Fund package maintenance!
Requires
- php: ^8.2
- illuminate/bus: ^12.0 || ^13.0
- illuminate/console: ^12.0 || ^13.0
- illuminate/database: ^12.0 || ^13.0
- illuminate/hashing: ^12.0 || ^13.0
- illuminate/http: ^12.0 || ^13.0
- illuminate/queue: ^12.0 || ^13.0
- illuminate/routing: ^12.0 || ^13.0
- illuminate/support: ^12.0 || ^13.0
- illuminate/validation: ^12.0 || ^13.0
Requires (Dev)
- laravel/pint: ^1.29.3
- orchestra/testbench: ^10.0
- phpunit/phpunit: ^11.5
README
Laravel backend package for a generic Post2Site MCP publishing contract.
The package handles the HTTP workflow, staging drafts, selected assets, validation envelopes, and publish confirmation. Host applications provide the content model through a Post2SiteAdapter; package DTOs do not define blog fields, categories, topics, locales, URL patterns, authors, or host markers.
Requirements
- PHP 8.2+
- Laravel 12 or 13
Installation
composer require n2ns/laravel-post2site
php artisan vendor:publish --tag=post2site-config
php artisan migrate
php artisan post2site:key "Production MCP"
Configure your MCP client with:
{
"CONTENT_API_BASE_URL": "https://your-host/api/v1/mcp",
"CONTENT_API_KEY": "the-key-printed-by-the-command"
}
By default, authentication uses API keys stored in post2site_api_keys. For local fixtures or controlled environments, POST2SITE_AUTH_DRIVER=static can be used with POST2SITE_API_KEY.
Contract
Default route prefix: /api/v1/mcp.
Discovery:
GET /capabilitiesGET /site-contextGET /editorial-policy
Inventory:
GET /inventory/resourcesGET /inventory/resources/{target_identifier}GET /inventory/statsPOST /inventory/duplicates
target_identifier may contain /; callers should percent-encode it in the URL path.
Drafts and assets:
POST /working-drafts/validateGET /draftsPOST /draftsGET /drafts/{draft_id}PATCH /drafts/{draft_id}POST /drafts/{draft_id}/validateGET /drafts/{draft_id}/previewPOST /drafts/{draft_id}/publishPOST /assets
Core payload shape:
{
"mode": "create",
"target_identifier": "host-resource-identifier",
"content_payload": {},
"client_metadata": {}
}
content_payload is a host-declared JSON object. The package stores it, passes it to the adapter, and reports validation issues using stable field paths such as content_payload.locales.en.title; it does not interpret host fields.
Host Adapter
Bind N2ns\LaravelPost2Site\Contracts\Post2SiteAdapter:
'bindings' => [ 'adapter' => App\Post2Site\HostPost2SiteAdapter::class, ],
There is no default content adapter. The package fails fast until the host binds a concrete Post2SiteAdapter.
The adapter provides capabilities, site context, editorial policy, inventory, duplicate checks, content validation, asset extraction, selected-asset storage, preview, and publish.
Publish requires:
- authenticated API key
publish_confirmed = true
The package validates, calls the host adapter publish method, and stores the draft publish result.
Stored Package State
The package owns only workflow state:
post2site_api_keys: database-backed API keys.post2site_drafts: staged server drafts, validation state, publish state, and host payload snapshots.post2site_assets: selected uploaded asset references and optional draft attribution.post2site_indexing_submissions: optional indexing submission bookkeeping for host integrations.
Host public content remains behind the Post2SiteAdapter.
Optional Indexing
The package includes an IndexingNotifier binding and an IndexNow notifier. IndexNow is disabled unless POST2SITE_INDEXNOW_ENABLED=true and POST2SITE_INDEXNOW_KEY are configured. The package does not expose a generic URL submission endpoint through the MCP contract.
Testing
composer test
composer pint:test
Documentation
License
This project is licensed under the MIT License.