Publishing to App Directories
Building a great chat app is only half the journey. Publishing it to AI host directories like the ChatGPT App Store gives your app access to hundreds of millions of users. This guide covers the submission process, requirements, and best practices for getting your app approved.
The Opportunity
AI assistants have rapidly become primary interfaces for millions of users:
- ChatGPT alone has over 800 million weekly active users
- Claude and other AI assistants are growing rapidly
- Users are increasingly comfortable completing tasks through conversation
Getting your app into these directories means reaching an audience that's actively looking for tools to help them accomplish goals, without the friction of traditional app discovery.
Unlike traditional app stores where users browse and download, AI app directories work differently. Users discover your app when the AI suggests it for relevant tasks, or when they explicitly invoke it.
Preparation Checklist
Before starting the submission process, ensure you have everything ready:
Technical Requirements
- Production MCP Server: Hosted remotely on HTTPS
- Domain Verification: Ability to place verification tokens
- OAuth Integration: If your app requires authentication
- Tool Annotations: Proper metadata on all tools
- Content Security Policy: Declared domains for network access
Business & Legal
- Privacy Policy: Publicly accessible URL
- Terms of Service: Publicly accessible URL
- Support Contact: Email or page for user support
- Business Verification: Platform account verification
Assets
- App Logo: Multiple sizes, light and dark variants
- Screenshots: 3-4 high-quality images of your widget
- Demo Video: Showing app capabilities in action
- Description Copy: Short and long form descriptions
Testing
- Positive Test Cases: 5+ scenarios showing intended use
- Negative Test Cases: 3+ scenarios showing boundary behavior
- Test Account: If authentication is required
Submission Process
Configure Your MCP Server for Production
Ensure your server is production-ready:
import { createUniversalServerApp } from '@pancakeapps/server';
const app = createUniversalServerApp({
name: 'your-app',
version: '1.0.0',
// Production settings
auth: {
type: 'oauth2',
clientId: process.env.OAUTH_CLIENT_ID,
authorizationUrl: 'https://your-service.com/oauth/authorize',
tokenUrl: 'https://your-service.com/oauth/token',
scopes: ['read', 'write'],
},
});
// Ensure all tools have proper annotations
app.tool({
name: 'get_user_data',
description: 'Fetch user profile and preferences',
annotations: {
readOnlyHint: true, // Doesn't modify data
openWorldHint: false, // Only accesses your service
destructiveHint: false, // No destructive actions
},
inputSchema: userDataSchema,
}, handler);Add Domain Verification
Host platforms require you to verify domain ownership. You'll need to place a verification token at a well-known path:
// Add verification endpoint
app.get('/.well-known/openai-apps-challenge', (req, res) => {
res.send(process.env.VERIFICATION_TOKEN);
});Or if using the PancakeJS server:
const app = createUniversalServerApp({
name: 'your-app',
verification: {
openai: process.env.OPENAI_VERIFICATION_TOKEN,
// Add other platforms as they become available
},
});Prepare Tool Annotations
Every tool needs proper annotations that honestly describe its behavior:
| Annotation | Meaning | Example |
|---|---|---|
readOnlyHint | Tool doesn't modify its environment | Fetching weather data |
openWorldHint | Tool interacts with external entities | Web search, public APIs |
destructiveHint | Tool performs destructive actions | Deleting files, canceling orders |
app.tool({
name: 'delete_item',
description: 'Remove an item from the user\'s collection',
annotations: {
readOnlyHint: false, // Modifies data
openWorldHint: false, // Only your service
destructiveHint: true, // Destructive action
},
inputSchema: z.object({
itemId: z.string(),
}),
}, async (input) => {
await deleteItem(input.itemId);
return textResult('Item deleted successfully');
});Be honest with annotations. Reviewers verify these claims, and misrepresentation can result in rejection or removal.
Create Test Cases
Prepare comprehensive test cases that reviewers will use to validate your app:
Positive Test Cases (5+ required)
Each case needs:
- Scenario description
- Exact user prompt
- Expected tool invocation
- Expected output format
{
"positive_cases": [
{
"scenario": "Search for Italian restaurants",
"prompt": "Find Italian restaurants near Times Square under $50",
"expected_tool": "search_restaurants",
"expected_output": {
"restaurants": [
{
"name": "string",
"cuisine": "Italian",
"price_range": "$$",
"location": "string"
}
]
}
},
{
"scenario": "Make a reservation",
"prompt": "Book a table for 4 at Carmine's tomorrow at 7pm",
"expected_tool": "make_reservation",
"expected_output": {
"confirmation": "string",
"restaurant": "Carmine's",
"party_size": 4,
"time": "string"
}
}
]
}Negative Test Cases (3+ required)
Show what's outside your app's scope:
{
"negative_cases": [
{
"scenario": "Request outside domain",
"prompt": "Find hotels near Times Square",
"reason": "App only handles restaurant searches, not hotels"
},
{
"scenario": "Unsupported action",
"prompt": "Cancel my Uber ride",
"reason": "App doesn't integrate with Uber"
}
]
}Prepare Visual Assets
App Logo
- 64×64 pixels minimum
- Light and dark variants
- Clear at small sizes
- No text in logo (use app name instead)
Screenshots
- 3-4 high-quality screenshots
- Show your widget in action
- Don't include chat interface elements (they'll be added)
- Demonstrate key features
Demo Video
- Keep it short (60-90 seconds)
- Show complete workflows
- Include all platforms (web, mobile if applicable)
- Demonstrate value proposition quickly
Submit for Review
Access the submission portal for your target platform and complete the form:
App Information
- App name (this is how users will invoke it)
- Short description (one-liner for listings)
- Long description (detailed features and use cases)
- Category selection
- Developer name and website
Legal Links
- Privacy policy URL
- Terms of service URL
- Support contact
Technical Configuration
- MCP server URL
- Domain verification
- Test credentials
- Test cases
Assets
- Logo uploads
- Screenshots
- Demo video link
Review Terms
- Agree to platform guidelines
- Confirm no prohibited content
- Verify business account
Review Guidelines
Platforms review apps across several dimensions:
Safety & Privacy
- Data handling: What data do you collect? How is it stored?
- Permissions: Do you request only necessary permissions?
- Authentication: Is OAuth properly implemented?
- CSP: Are network permissions appropriately scoped?
Functionality
- Tool behavior: Do tools work as described?
- Error handling: Does the app handle edge cases gracefully?
- Performance: Is the app responsive?
- Reliability: Does the app consistently work?
User Experience
- Widget design: Is the UI clear and usable?
- Theme support: Does the widget respect host themes?
- Responsiveness: Does the widget work at different sizes?
- Accessibility: Is the widget accessible?
Content Policies
- No prohibited content: No illegal, harmful, or deceptive content
- No ads: Advertising is typically not allowed in widgets
- Payment restrictions: Digital goods payments may be restricted
- Age-appropriate: Additional review for children-targeted apps
Best Practices for Approval
Write Clear Descriptions
Your description helps both reviewers and users understand your app:
❌ Bad: "Restaurant app with lots of features"
✅ Good: "Find and book restaurants based on cuisine,
location, and budget. Search thousands of restaurants,
read reviews, view menus, and make reservations,
all without leaving the conversation."Scope Appropriately
Apps with focused functionality are easier to review and more likely to be approved:
❌ "Do everything" app that tries to handle many domains
✅ "Restaurant finder" that does one thing excellentlyTest Thoroughly
Before submitting:
- Test all positive scenarios work correctly
- Verify negative scenarios are handled gracefully
- Check widget renders correctly in light and dark themes
- Ensure error states have helpful messages
- Validate on different viewport sizes
Provide Clear Test Instructions
Make it easy for reviewers:
Test Account:
- Email: test@example.com
- Password: SecureTestPass123
Test Scenarios:
1. Search for "sushi near downtown Seattle" → Should show ~10 results
2. Click any restaurant → Should show details widget
3. Click "Book Table" → Should show reservation form
4. Submit with party size 2, tomorrow 7pm → Should show confirmationPlatform-Specific Notes
ChatGPT App Directory
Requirements:
- OpenAI Platform account with business verification
- Adherence to OpenAI's Apps SDK UI guidelines
- Video demo required
Restrictions:
- No ads in widgets
- Digital goods payments not currently supported
- Physical goods sales allowed with proper verification
Timeline:
- Review typically takes 1-2 weeks
- You'll receive feedback if changes are needed
Submission URL: Access through your OpenAI Platform account dashboard
MCP Apps Ecosystem
MCP Apps is an open standard, so the submission process varies by host:
Claude Desktop:
- Currently supports local and remote MCP servers
- No centralized app directory yet
- Users add servers manually via config
Other Hosts:
- Check individual host documentation
- Standards are evolving as the ecosystem matures
Current Best Practice:
- Build your MCP server following the spec
- Document installation instructions
- Distribute through your own channels
- Monitor for host-specific app stores
Post-Approval
Once your app is approved:
Monitor Performance
- Track usage patterns
- Monitor error rates
- Collect user feedback
Iterate and Update
- Fix bugs promptly
- Add requested features
- Improve based on feedback
Manage Versions
const app = createUniversalServerApp({
name: 'your-app',
version: '1.1.0', // Bump for updates
});Significant updates may require re-review. Minor bug fixes usually don't.
Common Rejection Reasons
Learn from common mistakes:
| Issue | How to Avoid |
|---|---|
| Missing privacy policy | Ensure URL is public and accessible |
| Incorrect tool annotations | Verify annotations match actual behavior |
| Widget doesn't support dark theme | Test in both themes before submitting |
| Unclear app purpose | Write a specific, focused description |
| Failed test cases | Validate all test scenarios work |
| Missing error handling | Test edge cases and network failures |
| CSP too broad | Request only domains you actually need |