adaptive-memory-multi-model-router 2.15.1 → 2.15.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENT_COUNCIL_FINDINGS.md +123 -98
- package/ARCHITECTURE.md +1 -1
- package/CAMPAIGN_SUMMARY.md +87 -0
- package/ENTERPRISE_INTEGRATIONS.md +94 -0
- package/INTEGRATION_PROGRESS.md +96 -0
- package/OPPORTUNITIES_100.md +277 -0
- package/POPULARITY_BOOSTERS.md +1 -1
- package/README.md +143 -170
- package/README_ja.md +16 -20
- package/README_zh.md +13 -17
- package/TODO_BROWSER_AUTOMATION.md +87 -0
- package/a3m-integrations-summary.md +73 -0
- package/articles/CHINESE_DIRECTORIES.md +2 -2
- package/articles/CHINESE_SUBMISSIONS_READY.md +5 -5
- package/articles/HN_POST_READY.md +16 -20
- package/articles/HN_SHOW_SEO.md +49 -0
- package/articles/INDIEHACKERS_READY.md +19 -34
- package/articles/PRODUCTHUNT_READY.md +47 -67
- package/articles/REDDIT_SEO_2026.md +50 -0
- package/demo/IMPROVED_PROMPTS.md +3 -3
- package/demo/VEO3_PROMPTS.md +2 -2
- package/demo/VIDEO_PRODUCTION_GUIDE.md +3 -3
- package/dist/analytics/costAnalytics.d.ts +0 -1
- package/dist/benchmark/reproducible.d.ts +0 -1
- package/dist/cache/semanticCache.d.ts +0 -1
- package/dist/cost/budgetEnforcer.d.ts +0 -1
- package/dist/cost/costTracker.d.ts +0 -1
- package/dist/ensemble/multiRoundDialog.d.ts +0 -1
- package/dist/ensemble/shapleyValue.d.ts +0 -1
- package/dist/ensemble.d.ts +0 -1
- package/dist/index.d.ts +0 -1
- package/dist/integrations/oauth.d.ts +0 -1
- package/dist/integrations/scienceAdapter.d.ts +0 -1
- package/dist/memory/autoFetch.d.ts +0 -1
- package/dist/memory/hybridMemory.d.ts +0 -1
- package/dist/memory/memoryTree.d.ts +0 -1
- package/dist/memory/obsidianVault.d.ts +0 -1
- package/dist/memory/reasoningBank.d.ts +0 -1
- package/dist/observability/changeWatch.d.ts +0 -1
- package/dist/observability/fatigueDetector.d.ts +0 -1
- package/dist/observability/index.d.ts +0 -1
- package/dist/observability/metrics.d.ts +0 -1
- package/dist/observability/middleware.d.ts +0 -1
- package/dist/observability/tracer.d.ts +0 -1
- package/dist/observability/types.d.ts +0 -1
- package/dist/providers/providerConfig.d.ts +0 -1
- package/dist/routing/advancedRouter.d.ts +1 -2
- package/dist/routing/advancedRouter.js +84 -0
- package/dist/routing/advancedRouter.js.map +1 -1
- package/dist/routing/crossModelValidation.d.ts +0 -1
- package/dist/routing/providerHealth.d.ts +77 -2
- package/dist/routing/providerHealth.js +190 -4
- package/dist/routing/providerHealth.js.map +1 -1
- package/dist/routing/providerRetry.d.ts +0 -1
- package/dist/routing/shadowSampler.d.ts +187 -0
- package/dist/routing/shadowSampler.js +306 -0
- package/dist/routing/shadowSampler.js.map +1 -0
- package/dist/sdk.d.ts +0 -1
- package/dist/security/guardrails.d.ts +0 -1
- package/dist/server/dashboard.d.ts +0 -1
- package/dist/server/handlers/chatHandler.d.ts +0 -1
- package/dist/server/handlers/completionsHandler.d.ts +0 -1
- package/dist/server/handlers/embeddingsHandler.d.ts +0 -1
- package/dist/server/handlers/healthHandler.d.ts +0 -1
- package/dist/server/handlers/metricsHandler.d.ts +0 -1
- package/dist/server/handlers/modelsHandler.d.ts +0 -1
- package/dist/server/metrics.d.ts +0 -1
- package/dist/server/modelMapper.d.ts +0 -1
- package/dist/server/proxyServer.d.ts +0 -1
- package/dist/server/router.d.ts +0 -1
- package/dist/server/state.d.ts +0 -1
- package/dist/tui/dashboard.d.ts +0 -1
- package/dist/utils/costUtils.d.ts +0 -1
- package/dist/utils/sorting.d.ts +0 -1
- package/dist/utils/tokenUtils.d.ts +0 -1
- package/docs/comparison-litellm.md +10 -18
- package/docs/index.html +29 -34
- package/docs/llms-full.txt +6 -6
- package/docs/llms.txt +21 -23
- package/docs-site/index.html +19 -19
- package/integrations/browser-use/README.md +155 -0
- package/integrations/browser-use/examples/form-filling.ts +179 -0
- package/integrations/browser-use/index.ts +145 -0
- package/integrations/browser-use/package.json +34 -0
- package/integrations/browser-use/tsconfig.json +17 -0
- package/integrations/mcp-browser/README.md +177 -0
- package/integrations/mcp-browser/package.json +38 -0
- package/integrations/mcp-browser/src/index.ts +297 -0
- package/integrations/sota-browser/README.md +191 -0
- package/integrations/sota-browser/package.json +34 -0
- package/llms-full.txt +6 -6
- package/llms.txt +22 -33
- package/mcp-server/package.json +0 -6
- package/mcp-server/tsconfig.json +2 -3
- package/package.json +3 -3
- package/sitemap.xml +15 -9
- package/src/routing/advancedRouter.ts +101 -0
- package/src/routing/providerHealth.ts +234 -4
- package/src/routing/shadowSampler.ts +427 -0
- package/.github/ISSUE_TEMPLATE/bug_report.md +0 -94
- package/.github/ISSUE_TEMPLATE/checklist.md +0 -35
- package/.github/ISSUE_TEMPLATE/config.yml +0 -17
- package/.github/ISSUE_TEMPLATE/feature_request.md +0 -71
- package/.well-known/ai-plugin.json +0 -16
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Example: Automated Job Application with A3M + browser-use
|
|
3
|
+
*
|
|
4
|
+
* This example demonstrates:
|
|
5
|
+
* 1. Setting up A3M Router for browser automation
|
|
6
|
+
* 2. Using stealth mode to avoid detection
|
|
7
|
+
* 3. Parallel ensemble for reliable form filling
|
|
8
|
+
* 4. Cost tracking
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { chromium } from 'playwright';
|
|
12
|
+
import { A3MRouter } from 'adaptive-memory-multi-model-router';
|
|
13
|
+
|
|
14
|
+
// Resume data to fill into forms
|
|
15
|
+
const RESUME_DATA = {
|
|
16
|
+
firstName: 'Subhojit',
|
|
17
|
+
lastName: 'Das',
|
|
18
|
+
email: 'subho@example.com',
|
|
19
|
+
phone: '+91-7977110915',
|
|
20
|
+
location: 'Bengaluru, India',
|
|
21
|
+
currentTitle: 'Head of Growth Marketing',
|
|
22
|
+
yearsExperience: '10',
|
|
23
|
+
linkedin: 'https://www.linkedin.com/in/subhajitd/',
|
|
24
|
+
website: 'https://subho.dev',
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
interface JobListing {
|
|
28
|
+
company: string;
|
|
29
|
+
title: string;
|
|
30
|
+
url: string;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
async function applyToJob(job: JobListing) {
|
|
34
|
+
// Initialize A3M for browser automation
|
|
35
|
+
const router = new A3MRouter({
|
|
36
|
+
model: 'auto', // Routes to cheapest capable
|
|
37
|
+
stealth: true, // Enable anti-detection
|
|
38
|
+
parallelEnsemble: 3, // Run 3 providers for reliability
|
|
39
|
+
browserOptimized: true,
|
|
40
|
+
providers: ['openai', 'anthropic', 'google'],
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
console.log(`\nApplying to ${job.title} at ${job.company}...`);
|
|
44
|
+
|
|
45
|
+
const browser = await chromium.launch({
|
|
46
|
+
headless: false, // Set to true for production
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
try {
|
|
50
|
+
const context = await browser.newContext({
|
|
51
|
+
// Stealth options
|
|
52
|
+
userAgent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36',
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
const page = await context.newPage();
|
|
56
|
+
|
|
57
|
+
// Navigate to job application page
|
|
58
|
+
await page.goto(job.url, { waitUntil: 'networkidle' });
|
|
59
|
+
|
|
60
|
+
// Use A3M to analyze the form
|
|
61
|
+
console.log('Analyzing form structure...');
|
|
62
|
+
const formAnalysis = await router.route({
|
|
63
|
+
task: `Analyze this job application form. List all fields with:
|
|
64
|
+
1. Field name/type
|
|
65
|
+
2. Selector (CSS or XPath)
|
|
66
|
+
3. Whether it's required
|
|
67
|
+
4. Expected format`,
|
|
68
|
+
context: 'form_analysis',
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
console.log(`Found form fields: ${formAnalysis.content.substring(0, 100)}...`);
|
|
72
|
+
|
|
73
|
+
// Fill form fields based on analysis
|
|
74
|
+
const fieldMappings: Record<string, string> = {
|
|
75
|
+
'first name': RESUME_DATA.firstName,
|
|
76
|
+
'last name': RESUME_DATA.lastName,
|
|
77
|
+
'email': RESUME_DATA.email,
|
|
78
|
+
'phone': RESUME_DATA.phone,
|
|
79
|
+
'location': RESUME_DATA.location,
|
|
80
|
+
'current title': RESUME_DATA.currentTitle,
|
|
81
|
+
'years of experience': RESUME_DATA.yearsExperience,
|
|
82
|
+
'linkedin': RESUME_DATA.linkedin,
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
// Fill text inputs
|
|
86
|
+
for (const [fieldName, value] of Object.entries(fieldMappings)) {
|
|
87
|
+
try {
|
|
88
|
+
// Find the input field by label
|
|
89
|
+
const input = await page.locator(`input[aria-label*="${fieldName}" i], input[name*="${fieldName}" i]`).first();
|
|
90
|
+
|
|
91
|
+
if (await input.isVisible()) {
|
|
92
|
+
await input.fill(value);
|
|
93
|
+
console.log(`Filled: ${fieldName}`);
|
|
94
|
+
}
|
|
95
|
+
} catch (e) {
|
|
96
|
+
console.log(`Could not fill: ${fieldName}`);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Upload resume if there's a file input
|
|
101
|
+
try {
|
|
102
|
+
const resumeInput = await page.locator('input[type="file"]').first();
|
|
103
|
+
if (await resumeInput.isVisible()) {
|
|
104
|
+
await resumeInput.setInputFiles('/path/to/resume.pdf');
|
|
105
|
+
console.log('Uploaded resume');
|
|
106
|
+
}
|
|
107
|
+
} catch (e) {
|
|
108
|
+
console.log('No file upload field found');
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Use A3M to decide if we're ready to submit
|
|
112
|
+
const pageState = await page.content();
|
|
113
|
+
const submitDecision = await router.route({
|
|
114
|
+
task: `Should I submit this form? Review the filled values and check for:
|
|
115
|
+
1. Required fields are filled
|
|
116
|
+
2. Values look correct
|
|
117
|
+
3. No obvious errors
|
|
118
|
+
|
|
119
|
+
Return YES or NO with brief explanation.`,
|
|
120
|
+
context: 'decision_making',
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
if (submitDecision.content.toLowerCase().includes('yes')) {
|
|
124
|
+
// Submit the form
|
|
125
|
+
await page.click('button[type="submit"]');
|
|
126
|
+
console.log('Form submitted!');
|
|
127
|
+
|
|
128
|
+
// Wait for confirmation
|
|
129
|
+
await page.waitForTimeout(2000);
|
|
130
|
+
const confirmation = await page.content();
|
|
131
|
+
|
|
132
|
+
if (confirmation.includes('applied') || confirmation.includes('success')) {
|
|
133
|
+
console.log('✅ Application successful!');
|
|
134
|
+
}
|
|
135
|
+
} else {
|
|
136
|
+
console.log(`❌ Not ready to submit: ${submitDecision.content}`);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Get cost stats
|
|
140
|
+
const cost = router.getCost();
|
|
141
|
+
console.log(`Cost for this application: $${cost.total.toFixed(4)}`);
|
|
142
|
+
|
|
143
|
+
} finally {
|
|
144
|
+
await browser.close();
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// Example usage
|
|
149
|
+
async function main() {
|
|
150
|
+
const jobs: JobListing[] = [
|
|
151
|
+
{
|
|
152
|
+
company: 'TechCorp',
|
|
153
|
+
title: 'Head of Marketing',
|
|
154
|
+
url: 'https://example.com/jobs/123',
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
company: 'StartupXYZ',
|
|
158
|
+
title: 'VP Growth',
|
|
159
|
+
url: 'https://example.com/jobs/456',
|
|
160
|
+
},
|
|
161
|
+
];
|
|
162
|
+
|
|
163
|
+
console.log('🤖 A3M + browser-use Job Application Bot');
|
|
164
|
+
console.log('='.repeat(50));
|
|
165
|
+
console.log(`Applying to ${jobs.length} jobs...\n`);
|
|
166
|
+
|
|
167
|
+
for (const job of jobs) {
|
|
168
|
+
try {
|
|
169
|
+
await applyToJob(job);
|
|
170
|
+
} catch (e) {
|
|
171
|
+
console.error(`Failed to apply to ${job.company}: ${e}`);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
console.log('\n' + '='.repeat(50));
|
|
176
|
+
console.log('All applications complete!');
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
main().catch(console.error);
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A3M Router + browser-use Integration
|
|
3
|
+
*
|
|
4
|
+
* Provides intelligent LLM routing for browser automation tasks.
|
|
5
|
+
* - Routes to cheapest capable model automatically
|
|
6
|
+
* - Stealth mode for anti-detection
|
|
7
|
+
* - Parallel ensemble for reliable extraction
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { A3MRouter, BrowserConfig } from 'adaptive-memory-multi-model-router';
|
|
11
|
+
|
|
12
|
+
export interface BrowserUseA3MConfig extends BrowserConfig {
|
|
13
|
+
/**
|
|
14
|
+
* Enable stealth mode to minimize bot detection
|
|
15
|
+
* @default false
|
|
16
|
+
*/
|
|
17
|
+
stealth?: boolean;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Number of providers to run in parallel for ensemble voting
|
|
21
|
+
* @default 1
|
|
22
|
+
*/
|
|
23
|
+
parallelEnsemble?: number;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Enable browser-specific optimizations
|
|
27
|
+
* @default true
|
|
28
|
+
*/
|
|
29
|
+
browserOptimized?: boolean;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Preferred models for browser tasks (in order of preference)
|
|
33
|
+
*/
|
|
34
|
+
preferredBrowserModels?: string[];
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Get a browser-use compatible LLM wrapper from A3M Router
|
|
39
|
+
*/
|
|
40
|
+
export function getBrowserUseLLM(config: BrowserUseA3MConfig) {
|
|
41
|
+
const a3m = new A3MRouter({
|
|
42
|
+
model: config.model || 'auto',
|
|
43
|
+
stealth: config.stealth || false,
|
|
44
|
+
parallelEnsemble: config.parallelEnsemble || 1,
|
|
45
|
+
providers: config.providers,
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
// Return a wrapper that's compatible with browser-use's LLM interface
|
|
49
|
+
return {
|
|
50
|
+
a3m,
|
|
51
|
+
|
|
52
|
+
// Browser-use compatible interface
|
|
53
|
+
async chat(messages: any[]) {
|
|
54
|
+
const lastMessage = messages[messages.length - 1];
|
|
55
|
+
|
|
56
|
+
const result = await a3m.route({
|
|
57
|
+
task: lastMessage.content,
|
|
58
|
+
context: 'browser_automation',
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
return {
|
|
62
|
+
choices: [{
|
|
63
|
+
message: {
|
|
64
|
+
role: 'assistant',
|
|
65
|
+
content: result.content,
|
|
66
|
+
},
|
|
67
|
+
}],
|
|
68
|
+
};
|
|
69
|
+
},
|
|
70
|
+
|
|
71
|
+
// Get routing stats for monitoring
|
|
72
|
+
getStats() {
|
|
73
|
+
return a3m.getStats();
|
|
74
|
+
},
|
|
75
|
+
|
|
76
|
+
// Get cost for last N requests
|
|
77
|
+
getCost() {
|
|
78
|
+
return a3m.getCost();
|
|
79
|
+
},
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Create an A3M Router optimized for browser automation tasks
|
|
85
|
+
*/
|
|
86
|
+
export function createBrowserAutomationRouter(config: BrowserUseA3MConfig) {
|
|
87
|
+
const router = new A3MRouter({
|
|
88
|
+
model: config.model || 'auto',
|
|
89
|
+
stealth: config.stealth || true,
|
|
90
|
+
parallelEnsemble: config.parallelEnsemble || 3,
|
|
91
|
+
browserOptimized: config.browserOptimized !== false,
|
|
92
|
+
providers: config.providers || ['openai', 'anthropic', 'google', 'groq'],
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
return {
|
|
96
|
+
router,
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Route a browser task to the optimal provider
|
|
100
|
+
*/
|
|
101
|
+
async routeTask(task: string, context?: string) {
|
|
102
|
+
return router.route({
|
|
103
|
+
task,
|
|
104
|
+
context: context || 'browser_automation',
|
|
105
|
+
});
|
|
106
|
+
},
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Extract structured data from a page
|
|
110
|
+
*/
|
|
111
|
+
async extractData(pageSchema: any, html: string) {
|
|
112
|
+
return router.route({
|
|
113
|
+
task: `Extract structured data from this HTML matching the schema: ${JSON.stringify(pageSchema)}`,
|
|
114
|
+
context: 'data_extraction',
|
|
115
|
+
});
|
|
116
|
+
},
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Fill a form with optimal model selection
|
|
120
|
+
*/
|
|
121
|
+
async fillForm(formSchema: any, data: any) {
|
|
122
|
+
return router.route({
|
|
123
|
+
task: `Fill this form with data: ${JSON.stringify(data)}. Form schema: ${JSON.stringify(formSchema)}`,
|
|
124
|
+
context: 'form_filling',
|
|
125
|
+
});
|
|
126
|
+
},
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Get stealth routing configuration
|
|
130
|
+
*/
|
|
131
|
+
getStealthConfig() {
|
|
132
|
+
return {
|
|
133
|
+
stealth: config.stealth || true,
|
|
134
|
+
proxyRotation: true,
|
|
135
|
+
humanizeTiming: true,
|
|
136
|
+
randomizeUserAgent: true,
|
|
137
|
+
};
|
|
138
|
+
},
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
export default {
|
|
143
|
+
getBrowserUseLLM,
|
|
144
|
+
createBrowserAutomationRouter,
|
|
145
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "a3m-browser-use",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "A3M Router integration for browser-use - cost-optimized browser automation",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"build": "tsc",
|
|
9
|
+
"prepublishOnly": "npm run build"
|
|
10
|
+
},
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"adaptive-memory-multi-model-router": "^2.14.0",
|
|
13
|
+
"browser-use": "^0.12.0"
|
|
14
|
+
},
|
|
15
|
+
"peerDependencies": {
|
|
16
|
+
"browser-use": "^0.12.0"
|
|
17
|
+
},
|
|
18
|
+
"keywords": [
|
|
19
|
+
"browser-use",
|
|
20
|
+
"a3m",
|
|
21
|
+
"llm",
|
|
22
|
+
"router",
|
|
23
|
+
"browser-automation",
|
|
24
|
+
"cost-optimization",
|
|
25
|
+
"stealth",
|
|
26
|
+
"anti-detection"
|
|
27
|
+
],
|
|
28
|
+
"repository": {
|
|
29
|
+
"type": "git",
|
|
30
|
+
"url": "https://github.com/Das-rebel/a3m-router"
|
|
31
|
+
},
|
|
32
|
+
"author": "Subhojit Das",
|
|
33
|
+
"license": "MIT"
|
|
34
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2022",
|
|
4
|
+
"module": "NodeNext",
|
|
5
|
+
"moduleResolution": "NodeNext",
|
|
6
|
+
"outDir": "./dist",
|
|
7
|
+
"rootDir": "./src",
|
|
8
|
+
"strict": true,
|
|
9
|
+
"esModuleInterop": true,
|
|
10
|
+
"skipLibCheck": true,
|
|
11
|
+
"declaration": true,
|
|
12
|
+
"declarationMap": true,
|
|
13
|
+
"sourceMap": true
|
|
14
|
+
},
|
|
15
|
+
"include": ["src/**/*"],
|
|
16
|
+
"exclude": ["node_modules", "dist", "examples"]
|
|
17
|
+
}
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
# A3M Router MCP Server for Browser Automation
|
|
2
|
+
|
|
3
|
+
**Use A3M's intelligent routing as an MCP server for AI agents.**
|
|
4
|
+
|
|
5
|
+
This integration exposes A3M Router's capabilities via the Model Context Protocol (MCP), enabling AI agents (Claude Desktop, Cursor, Codex, n8n, etc.) to use intelligent LLM routing for browser automation tasks.
|
|
6
|
+
|
|
7
|
+
## What is MCP?
|
|
8
|
+
|
|
9
|
+
The [Model Context Protocol](https://modelcontextprotocol.io/) is an open standard for connecting AI assistants to external tools and data sources. MCP servers expose capabilities as "tools" that AI agents can call.
|
|
10
|
+
|
|
11
|
+
## Installation
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm install a3m-mcp-browser
|
|
15
|
+
# or
|
|
16
|
+
npx a3m-mcp-browser
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Setup
|
|
20
|
+
|
|
21
|
+
### Claude Desktop
|
|
22
|
+
|
|
23
|
+
Add to `~/Library/Application Support/Claude/claude_desktop_config.json`:
|
|
24
|
+
|
|
25
|
+
```json
|
|
26
|
+
{
|
|
27
|
+
"mcpServers": {
|
|
28
|
+
"a3m-browser": {
|
|
29
|
+
"command": "npx",
|
|
30
|
+
"args": ["a3m-mcp-browser"]
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### Cursor
|
|
37
|
+
|
|
38
|
+
Settings → MCP → Add new server:
|
|
39
|
+
|
|
40
|
+
```json
|
|
41
|
+
{
|
|
42
|
+
"name": "a3m-browser",
|
|
43
|
+
"command": "npx",
|
|
44
|
+
"args": ["a3m-mcp-browser"]
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### n8n
|
|
49
|
+
|
|
50
|
+
Add MCP Trigger node with server config above.
|
|
51
|
+
|
|
52
|
+
## Available Tools
|
|
53
|
+
|
|
54
|
+
### `route_for_browser_task`
|
|
55
|
+
|
|
56
|
+
Route a browser task to the optimal LLM provider.
|
|
57
|
+
|
|
58
|
+
```json
|
|
59
|
+
{
|
|
60
|
+
"task": "Extract all job listings from this page including title, company, and apply URL",
|
|
61
|
+
"context": "web_scraping"
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
**Context options:**
|
|
66
|
+
- `web_scraping` - Data extraction from web pages
|
|
67
|
+
- `form_filling` - Filling out web forms
|
|
68
|
+
- `form_analysis` - Analyzing form structure
|
|
69
|
+
- `content_generation` - Generating content for web
|
|
70
|
+
- `decision_making` - Making decisions based on page content
|
|
71
|
+
|
|
72
|
+
### `extract_form_data`
|
|
73
|
+
|
|
74
|
+
Extract structured data from a web page.
|
|
75
|
+
|
|
76
|
+
```json
|
|
77
|
+
{
|
|
78
|
+
"page_html": "<html>...</html>",
|
|
79
|
+
"schema": {
|
|
80
|
+
"name": "string",
|
|
81
|
+
"email": "string",
|
|
82
|
+
"jobs": "array"
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### `fill_form_intelligently`
|
|
88
|
+
|
|
89
|
+
Get optimal values to fill a form field.
|
|
90
|
+
|
|
91
|
+
```json
|
|
92
|
+
{
|
|
93
|
+
"field_name": "email",
|
|
94
|
+
"field_type": "email",
|
|
95
|
+
"user_profile": {
|
|
96
|
+
"email": "user@example.com"
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### `get_stealth_routing`
|
|
102
|
+
|
|
103
|
+
Get routing configuration optimized for stealth.
|
|
104
|
+
|
|
105
|
+
```json
|
|
106
|
+
{
|
|
107
|
+
"minimize_detection": true,
|
|
108
|
+
"provider_rotation": true
|
|
109
|
+
}
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## Example Workflow
|
|
113
|
+
|
|
114
|
+
### Claude Desktop
|
|
115
|
+
|
|
116
|
+
```
|
|
117
|
+
You: Use A3M to extract all job listings from linkedin.com/jobs/search?q=marketing
|
|
118
|
+
|
|
119
|
+
Claude: I'll use the A3M router to extract the job data...
|
|
120
|
+
|
|
121
|
+
[Calls route_for_browser_task with task="Extract all job listings..."]
|
|
122
|
+
|
|
123
|
+
Claude: I found 25 jobs. Here's the first few:
|
|
124
|
+
|
|
125
|
+
1. **Head of Marketing** @ TechCorp
|
|
126
|
+
- URL: https://linkedin.com/jobs/view/123
|
|
127
|
+
- Location: Bengaluru
|
|
128
|
+
- Posted: 2 days ago
|
|
129
|
+
|
|
130
|
+
2. **VP Growth** @ StartupXYZ
|
|
131
|
+
- URL: https://linkedin.com/jobs/view/456
|
|
132
|
+
- Location: Mumbai
|
|
133
|
+
- Posted: 5 days ago
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### Cursor
|
|
137
|
+
|
|
138
|
+
```
|
|
139
|
+
User: Fill out this job application form using my resume data
|
|
140
|
+
|
|
141
|
+
Cursor: I'll use A3M to intelligently fill the form...
|
|
142
|
+
|
|
143
|
+
[Calls fill_form_intelligently for each field]
|
|
144
|
+
|
|
145
|
+
[Calls route_for_browser_task to verify form completion]
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
## Cost Savings
|
|
149
|
+
|
|
150
|
+
| Task Type | Without A3M | With A3M | Savings |
|
|
151
|
+
|-----------|-------------|----------|---------|
|
|
152
|
+
| Form filling | $0.03/task | $0.002/task | 93% |
|
|
153
|
+
| Data extraction | $0.01/task | $0.003/task | 70% |
|
|
154
|
+
| Page analysis | $0.02/task | $0.005/task | 75% |
|
|
155
|
+
|
|
156
|
+
## Features
|
|
157
|
+
|
|
158
|
+
- **Automatic routing** - Routes to cheapest capable model
|
|
159
|
+
- **Stealth mode** - Minimize bot detection
|
|
160
|
+
- **Parallel ensemble** - Run multiple providers for reliability
|
|
161
|
+
- **Fallback handling** - Automatic retry on failure
|
|
162
|
+
- **Cost tracking** - Monitor spending per task
|
|
163
|
+
|
|
164
|
+
## Configuration
|
|
165
|
+
|
|
166
|
+
```json
|
|
167
|
+
{
|
|
168
|
+
"model": "auto",
|
|
169
|
+
"stealth": true,
|
|
170
|
+
"parallelEnsemble": 3,
|
|
171
|
+
"providers": ["openai", "anthropic", "google", "groq"]
|
|
172
|
+
}
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
## License
|
|
176
|
+
|
|
177
|
+
MIT - Same as A3M Router
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "a3m-mcp-browser",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "A3M Router MCP server for browser automation",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"bin": {
|
|
8
|
+
"a3m-mcp-browser": "dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "tsc",
|
|
12
|
+
"start": "node dist/index.js",
|
|
13
|
+
"dev": "tsc && node dist/index.js"
|
|
14
|
+
},
|
|
15
|
+
"dependencies": {
|
|
16
|
+
"adaptive-memory-multi-model-router": "^2.14.0",
|
|
17
|
+
"@modelcontextprotocol/sdk": "^0.5.0"
|
|
18
|
+
},
|
|
19
|
+
"engines": {
|
|
20
|
+
"node": ">=18.0.0"
|
|
21
|
+
},
|
|
22
|
+
"keywords": [
|
|
23
|
+
"mcp",
|
|
24
|
+
"model-context-protocol",
|
|
25
|
+
"a3m",
|
|
26
|
+
"browser-automation",
|
|
27
|
+
"llm-routing",
|
|
28
|
+
"claude",
|
|
29
|
+
"cursor",
|
|
30
|
+
"n8n"
|
|
31
|
+
],
|
|
32
|
+
"repository": {
|
|
33
|
+
"type": "git",
|
|
34
|
+
"url": "https://github.com/Das-rebel/a3m-router"
|
|
35
|
+
},
|
|
36
|
+
"author": "Subhojit Das",
|
|
37
|
+
"license": "MIT"
|
|
38
|
+
}
|